Load libraries and data

root.dir <- "~/OneDrive/projects/"
project.dir <- paste0(root.dir,"PDX/")
source(paste0(root.dir,"R.utils/RNASEQ.utils.R"))

Attaching package: 'limma'

The following object is masked from 'package:BiocGenerics':

    plotMA



Attaching package: 'scales'

The following object is masked from 'package:ggbio':

    rescale
source(paste0(project.dir,"src/load.PDX.R"))
rnaseq <- get.PDX()
|--------------------------------------------------|
|==================================================|
meta <- load.meta()
meta <- subset.meta(meta,meta[,project=="drug.selu"])
rnaseq <- subset.PDX(rnaseq, rnaseq$meta[,Sample.name] %in% meta[,Sample.name])

QC

read.depth.plots(rnaseq$meta)

We should remove the runs that contain very few reads before we merge otherwise they could bias the subsequent analysis.

rnaseq <- subset.PDX(rnaseq, rnaseq$meta[,human.library.size>1E6])

Repeat QC plots:

read.depth.plots(rnaseq$meta)

rnaseq <- merge.PDX(rnaseq)
rnaseq$meta <- merge(rnaseq$meta,meta,sort=F)
unique(rnaseq$meta[,.(merged.lanes,as.numeric(as.factor(merged.lanes)))])
                                                                                                                                                                                                              merged.lanes
1: SLX-14082:HMW3VBBXX:s_4;SLX-14082:HMW3VBBXX:s_5;SLX-14082:HMW3VBBXX:s_6;SLX-14082:HMW3WBBXX:s_2;SLX-14082:HMW3WBBXX:s_3;SLX-14082:HMW3WBBXX:s_4;SLX-14082:HMW3WBBXX:s_5;SLX-14082:HMW3WBBXX:s_6;SLX-14082:HMW5MBBXX:s_1
2:                                                                                                                                                 SLX-14085:HL7TLBBXX:s_4;SLX-14085:HLCCLBBXX:s_5;SLX-14085:HLGY5BBXX:s_7
3:                                                                                                                                                 SLX-14086:HK2C7BBXX:s_6;SLX-14086:HK2C7BBXX:s_7;SLX-14086:HK2C7BBXX:s_8
4:                                                                                                                                                                                                 SLX-14906:HLKN7BBXX:s_5
   V2
1:  1
2:  2
3:  3
4:  4
rnaseq$meta[,merged.lanes:=as.numeric(as.factor(merged.lanes))]

What samples remain after all that QC:

table(unique(rnaseq$meta[,.(PDX,Treatment,Mouse)])[,.(PDX,Treatment)])
           Treatment
PDX         Selumetinib Unknown Vehicle
  HCI009              4       0       6
  STG139              5       0       5
  STG316              3       0       2
  VHIO098             5       1       4
  VHIO098OR           7       0       7

Note that the VHIO098 samples contain duplicates (as noted by mice numbers).

rnaseq$meta[,.N,.(Mouse,PDX,Treatment)][N>1]
   Mouse     PDX   Treatment N
1: 29378 VHIO098 Selumetinib 2
2: 29382 VHIO098 Selumetinib 2
3: 29358 VHIO098 Selumetinib 2
4: 29383 VHIO098 Selumetinib 2
5: 29381 VHIO098     Vehicle 2
6: 29379 VHIO098     Vehicle 2

Let’s use these duplicates to see if the assignment of human and mouse reads suffered by reducing to SE50 sequencing Note: merged.lane==1 –> SLX-14082; which is SE50)

x <- rnaseq$meta[Mouse %in% rnaseq$meta[,.N,.(Mouse,PDX,Treatment)][N>1,Mouse]][order(Mouse),.(Sample.name,Mouse,merged.lanes,mouse.library.size/(mouse.library.size+human.library.size))]
ggplot(x) + aes(x=Mouse,y=V4,colour=factor(merged.lanes)) + geom_point(size=5) + theme_wsj() + coord_flip()

There does not appear to be a signifgant change in the mouse fraction due to sequencing. However, lane 4 that which contains all the duplicates (news!), has consistantly lower amounts of mouse. I do not know why all the duplicates are found within SLX-14906. Are all of SLX-14906 duplicates?

rnaseq$meta[Mouse %in% rnaseq$meta[merged.lanes==4,Mouse]][order(Mouse),.(Sample.name,merged.lanes,Treatment,Processing.batch)]
                        Sample.name merged.lanes   Treatment Processing.batch
 1:     VHIO098-T1-x03-16.029358-T1            1 Selumetinib               NA
 2: VHIO098-T1-x03-16.029358-C1-Sel            4 Selumetinib                2
 3:      VHIO09-T1-x03-16.029378-T1            1 Selumetinib               NA
 4: VHIO098-T1-x03-16.029378-C1-Sel            4 Selumetinib                2
 5:     VHIO098-X3_29379_Vehicle_R1            3     Vehicle                1
 6: VHIO098-T1-x03-16.029379-C1-Veh            4     Vehicle                2
 7:     VHIO098-X3_29381_Vehicle_R1            2     Vehicle                1
 8: VHIO098-T1-x03-16.029381-C1-Veh            4     Vehicle                2
 9:     VHIO098-T1-x03-16.029382-T1            1 Selumetinib               NA
10: VHIO098-T1-x03-16.029382-C1-Sel            4 Selumetinib                2
11:        VHIO098-X3_29383_Selu_R1            2 Selumetinib                1
12: VHIO098-T1-x03-16.029383-C1-Sel            4 Selumetinib                2
13: VHIO098-T1-x03-16.029384-C1-Sel            4 Selumetinib                2
14: VHIO098-T1-x03-16.029386-C1-Veh            4     Vehicle                2

There appears to be duplication depending on the “processing batch”. I need to confirm with Dimitra what exactly this was in reference to and, potentially, fill in the “NAs”. The meta data would suggest that all the “NAs” should be 1.

—> After talking to Dim, I can confirm that all of SLX-14906 consisted of samples processed in a different manner to the rest. For ease, let us remove these samples from the analysis.

rnaseq <- subset.PDX(rnaseq,rnaseq$meta$merged.lanes!=4)

Let us check again the mouse fractions w.r.t. all sequencing runs.

ggplot(rnaseq$meta[,.(mouse.library.size/(mouse.library.size+human.library.size),merged.lanes)]) + aes(x=factor(merged.lanes), fill = factor(merged.lanes), y = V1) + geom_boxplot() + geom_jitter(width=0.1)

Both of the above indicate that we have not lost sensitivity in reducing the our read lengths.

Cellularity changes

Let’s just see whether there is a difference in the PDXs cellularity as we saw changes with the Olaparib drug treatment.

x <- melt(rnaseq$meta,id.vars=c("Sample.name","PDX","Treatment"),measure.vars = c("mouse.library.size","human.library.size"))
x[,value:=value/sum(value),Sample.name]
ggplot(x[variable=="mouse.library.size"]) + aes(x=Treatment,y=value,fill=Treatment) + geom_boxplot() + theme(axis.text.x=element_text(angle=90,hjust=1)) + facet_wrap(~PDX,scales = "free_y")

There does not appear to be a systematic change in the cellularity with treatment. Note that selu is a far more targeted therapy than olap, and hence may not change the stroma-tumor fractions as much.

PCAs

pca <- pca.run(rnaseq$human)
pca <- cbind(rnaseq$meta,pca)
pca$merged.lanes <- factor(pca$merged.lanes)
ggpairs(pca, columns=c('PC1', 'PC2', 'PC3', "human.library.size"),mapping=aes(color=PDX), upper=list(continuous='cor'))

ggpairs(pca, columns=c('PC1', 'PC2', 'PC3', "human.library.size"),mapping=aes(color=Treatment), upper=list(continuous='cor'))

ggpairs(pca, columns=c('PC1', 'PC2', 'PC3', "human.library.size"),mapping=aes(color=merged.lanes), upper=list(continuous='cor'))  

There appears a large batch effect associated with the sequencing. Outwith of that there is also some grouping based on pdx type, while nothing notable with regards to treatment.

rnaseq$meta[,.N,.(merged.lanes,PDX,Treatment)][order(merged.lanes)]
    merged.lanes       PDX   Treatment N
 1:            1 VHIO098OR Selumetinib 7
 2:            1 VHIO098OR     Vehicle 7
 3:            1    HCI009     Vehicle 1
 4:            1   VHIO098 Selumetinib 3
 5:            1   VHIO098     Unknown 1
 6:            1    STG139 Selumetinib 4
 7:            1    HCI009 Selumetinib 2
 8:            1    STG139     Vehicle 4
 9:            1    STG316     Vehicle 1
10:            2    HCI009     Vehicle 3
11:            2   VHIO098 Selumetinib 1
12:            2    STG316 Selumetinib 2
13:            2    STG139     Vehicle 1
14:            2   VHIO098     Vehicle 1
15:            2    HCI009 Selumetinib 1
16:            3    HCI009     Vehicle 2
17:            3    HCI009 Selumetinib 1
18:            3    STG139 Selumetinib 1
19:            3   VHIO098     Vehicle 2
20:            3    STG316 Selumetinib 1
21:            3    STG316     Vehicle 1
    merged.lanes       PDX   Treatment N

Let us repeat both the above PCAs using batch correction to account for the sequencing.

pca <- pca.prep(rnaseq$human)
pca <- with(rnaseq$meta,removeBatchEffect(pca,design = model.matrix(~ PDX + Treatment),batch = merged.lanes))
pca <- prcomp(t(pca),scale=T)
summary(pca)
Importance of components:
                           PC1     PC2     PC3    PC4     PC5     PC6     PC7     PC8     PC9    PC10    PC11   PC12    PC13    PC14    PC15    PC16    PC17   PC18    PC19    PC20
Standard deviation     22.5364 13.5307 11.3808 8.2155 5.07235 3.54701 2.87981 2.76189 2.49514 2.32141 2.09300 1.9501 1.90958 1.82024 1.73663 1.61807 1.58588 1.4480 1.37109 1.32881
Proportion of Variance  0.5079  0.1831  0.1295 0.0675 0.02573 0.01258 0.00829 0.00763 0.00623 0.00539 0.00438 0.0038 0.00365 0.00331 0.00302 0.00262 0.00252 0.0021 0.00188 0.00177
Cumulative Proportion   0.5079  0.6910  0.8205 0.8880 0.91372 0.92630 0.93459 0.94222 0.94844 0.95383 0.95821 0.9620 0.96566 0.96898 0.97199 0.97461 0.97713 0.9792 0.98110 0.98287
                          PC21    PC22    PC23    PC24    PC25    PC26    PC27    PC28    PC29    PC30    PC31    PC32    PC33    PC34    PC35    PC36    PC37    PC38    PC39
Standard deviation     1.28813 1.16859 1.11535 1.09041 1.06163 1.02163 0.98324 0.90228 0.89011 0.86423 0.81558 0.81330 0.74471 0.72684 0.71666 0.71209 0.67123 0.64245 0.60594
Proportion of Variance 0.00166 0.00137 0.00124 0.00119 0.00113 0.00104 0.00097 0.00081 0.00079 0.00075 0.00067 0.00066 0.00055 0.00053 0.00051 0.00051 0.00045 0.00041 0.00037
Cumulative Proportion  0.98453 0.98589 0.98714 0.98833 0.98945 0.99050 0.99146 0.99228 0.99307 0.99382 0.99448 0.99514 0.99570 0.99623 0.99674 0.99725 0.99770 0.99811 0.99848
                          PC40    PC41    PC42    PC43    PC44      PC45      PC46      PC47
Standard deviation     0.60359 0.57972 0.55428 0.53345 0.47942 1.001e-14 4.473e-15 3.181e-15
Proportion of Variance 0.00036 0.00034 0.00031 0.00028 0.00023 0.000e+00 0.000e+00 0.000e+00
Cumulative Proportion  0.99884 0.99918 0.99949 0.99977 1.00000 1.000e+00 1.000e+00 1.000e+00
pca <- cbind(rnaseq$meta,pca$x)
pca$merged.lanes <- factor(pca$merged.lanes)
ggpairs(pca, columns=c('PC1', 'PC2', 'PC3', "human.library.size"),mapping=aes(color=PDX), upper=list(continuous='cor'))

ggpairs(pca, columns=c('PC1', 'PC2', 'PC3', "human.library.size"),mapping=aes(color=Treatment), upper=list(continuous='cor'))

ggpairs(pca, columns=c('PC1', 'PC2', 'PC3', "human.library.size"),mapping=aes(color=merged.lanes), upper=list(continuous='cor'))  

Given the construction of the meta data, it’s hard to remove the effect of the sequencing from the variables of interest. As such, we get only a small reduction in the sequencing dominating the variablility.

Let’s plot the different PDX arms individually.

for(pdx in unique(rnaseq$meta$PDX)){
  x <- subset.PDX(rnaseq, rnaseq$meta[,pdx == PDX])
  pca <- pca.run(x$human)
  pca <- cbind(x$meta,pca)
  pca$merged.lanes <- factor(pca$merged.lanes)
  print(ggpairs(pca, columns=c('PC1', 'PC2', 'PC3', "human.library.size"),mapping=aes(color=Treatment,shape=merged.lanes), upper=list(continuous='cor'))  + ggtitle(pdx))
}

We are buggered by the sequencing…. :(

Since its not obvious by the grouping, what the unknown sample is from, I will remove it.

rnaseq <- subset.PDX(rnaseq,rnaseq$meta$Treatment!="Unknown")

Key questions

  • Genes of interest: EGFR, apoptotic genes (bcl2, mcl1, bax)
  • Are there any systematic differences between the control and treated groups?
  • Are there any traits/markers that define the speed with which resistance is devloped in the treated groups?
  • Is resistance developed in different manners between the treated samples?

Model: ~ drug + pdx

All data

sequencing <- rnaseq$meta[,factor(merged.lanes)]
treatment <- rnaseq$meta[,Treatment]
pdx <- rnaseq$meta[,PDX]
d <- model.matrix(~ 0 + treatment + pdx + sequencing)
cont.matrix <- matrix(c(1,-1,rep(0,dim(d)[2]-2)), dim(d)[2], 1)
colnames(cont.matrix) <- c("Selu.minus.control")
rownames(cont.matrix) <- colnames(d)
cont.matrix
                     Selu.minus.control
treatmentSelumetinib                  1
treatmentVehicle                     -1
pdxSTG139                             0
pdxSTG316                             0
pdxVHIO098                            0
pdxVHIO098OR                          0
sequencing2                           0
sequencing3                           0
#Perform DE
DE.data <- DE.run(rnaseq$human,d,2,cont.matrix = cont.matrix)

#Top DE genes table
DE <- topTable.annotated.DE(DE.data$efit,p.val = 0.05)
No DE genes
if(nrow(DE)!=0){
  table(DE[,direction])
  DE[direction=="up.reg",.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)]
  DE[direction=="down.reg",.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)]
#Pheatmap w/ batch correction
  i <- match(DE$ENSEMBL,rownames(DE.data$v$E))
  y <- removeBatchEffect(DE.data$v$E[i,],design = model.matrix(~drug), batch= pdx)
  labels.col <- rep("",nrow(rnaseq$meta))
  labels.row <- DE$SYMBOL
  ann.col <- as.data.frame(rnaseq$meta[,.(pdx,drug)])
  rownames(ann.col) <- rnaseq$meta[,Sample.name]
  pheatmap(y,labels_col=labels.col,labels_row=labels.row,annotation_col = ann.col,scale="row")
}
#GSEA - c6
gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c6,0.05)
'select()' returned 1:many mapping between keys and columns
gsea[Direction=="Up",.(rn,NGenes,Direction,FDR)]
Empty data.table (0 rows) of 4 cols: rn,NGenes,Direction,FDR
gsea[Direction=="Down",.(rn,NGenes,Direction,FDR)]
Empty data.table (0 rows) of 4 cols: rn,NGenes,Direction,FDR
#GSEA - c2
gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c2,0.05)
'select()' returned 1:many mapping between keys and columns
gsea[Direction=="Up",.(rn,NGenes,Direction,FDR)]
                                         rn NGenes Direction        FDR
1: NIKOLSKY_BREAST_CANCER_8Q23_Q24_AMPLICON    142        Up 0.03267419
gsea[Direction=="Down",.(rn,NGenes,Direction,FDR)]
                                  rn NGenes Direction        FDR
1: REACTOME_PEPTIDE_CHAIN_ELONGATION     85      Down 0.03267419
2:                     KEGG_RIBOSOME     85      Down 0.03267419
# ssGSEA
ssGSEA.data <- ssGSEA.run(DE.data$v$E,Hs.c6,d,cont.matrix=cont.matrix)
'select()' returned 1:many mapping between keys and columns
Error in .local(expr, gset.idx.list, ...) : 
  unused argument (rnaseq = TRUE)

The lack of any results is unsuprising as this statistical model is the most simplistic; not presuming that different models react differently to the drug, espcially with a resistant model included, is foolish. Also, the sequencing is dominating all the variability.

Genes of Interest

These genes were found in the scRNAseq data to be notable:

rr genes <- c(4, 1, ,1A,,3K8,1) ids <- mapIds(org.Hs.eg.db,keys=genes,keytype = ,column = , multiVals = )

'select()' returned 1:1 mapping between keys and columns

rr y <- DE.data\(v\)E[match(ids,rownames(DE.data$v)),] rownames(y) <- genes y <- removeBatchEffect(y,design = model.matrix(~treatment), batch=pdx, batch2 = sequencing) for(i in 1:length(ids)){ x <- y[i,] stripchart(x~treatment*pdx,vertical=TRUE,las=2,cex.axis=0.8,pch=16,col=1:2,method=,main=genes[i]) }

Shifts of mean w.r.t. PDX models

Repeat above with median (less affected by outliers)

Pathways of interest

Let us also check the LEF1 signature, which showed a response in the scRNA-seq data between response and resistence samples; a comparison we can’t perform due to sample numbers.

Shifts of mean w.r.t. PDX models

Repeat above with median (less affected by outliers)

Model: ~ drug:pdx

VHIO098

Only VHIO098-naive (Model: ~ drug)

VHI <- subset.PDX(rnaseq,rnaseq$meta[,PDX=="VHIO098" & Treatment!="Unknown"])
treatment <- VHI$meta[,Treatment]
sequencing <- VHI$meta[,factor(merged.lanes)]
#d <- model.matrix(~ 0 + treatment + sequencing)
d <- model.matrix(~ 0 + treatment) #<- Bad Ali
cont.matrix <- matrix(c(1,-1,rep(0,dim(d)[2]-2)), dim(d)[2], 1)
colnames(cont.matrix) <- c("Selu.minus.control")
rownames(cont.matrix) <- colnames(d)
cont.matrix
                     Selu.minus.control
treatmentSelumetinib                  1
treatmentVehicle                     -1
#Perform DE
DE.data <- DE.run(VHI$human,d,2,cont.matrix = cont.matrix)

#Top DE genes table
DE <- topTable.annotated.DE(DE.data$efit,p.val = 0.5)
'select()' returned 1:many mapping between keys and columns

Only VHIO098OR (Model: ~ drug)

VHIO.OR <- subset.PDX(rnaseq,rnaseq$meta[,PDX=="VHIO098OR"])
treatment <- VHIO.OR$meta[,Treatment]
d <- model.matrix(~ 0 + treatment)
cont.matrix <- matrix(c(1,-1,rep(0,dim(d)[2]-2)), dim(d)[2], 1)
colnames(cont.matrix) <- c("Selu.minus.control")
rownames(cont.matrix) <- colnames(d)
cont.matrix
                     Selu.minus.control
treatmentSelumetinib                  1
treatmentVehicle                     -1
#Perform DE
DE.data <- DE.run(VHIO.OR$human,d,2,cont.matrix = cont.matrix)

#Top DE genes table
DE <- topTable.annotated.DE(DE.data$efit,p.val = 0.05)
No DE genes
if(nrow(DE)!=0){
  table(DE[,direction])
  DE[direction=="up.reg",.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)]
  DE[direction=="down.reg",.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)]
#Pheatmap w/ batch correction
  i <- match(DE$ENSEMBL,rownames(DE.data$v$E))
  y <- removeBatchEffect(DE.data$v$E[i,],design = model.matrix(~drug), batch= pdx)
  labels.col <- rep("",nrow(VHIO.OR$meta))
  labels.row <- DE$SYMBOL
  ann.col <- as.data.frame(VHIO.OR$meta[,.(pdx,drug)])
  rownames(ann.col) <- VHIO.OR$meta[,Sample.name]
  pheatmap(y,labels_col=labels.col,labels_row=labels.row,annotation_col = ann.col,scale="row")
}
#GSEA - c2
gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c2,0.05)
'select()' returned 1:many mapping between keys and columns
gsea[Direction=="Up",.(rn,NGenes,Direction,FDR)]
Empty data.table (0 rows) of 4 cols: rn,NGenes,Direction,FDR
gsea[Direction=="Down",.(rn,NGenes,Direction,FDR)]
                                                                     rn NGenes Direction         FDR
1:                                                        KEGG_RIBOSOME     84      Down 0.001011085
2:                                    REACTOME_PEPTIDE_CHAIN_ELONGATION     83      Down 0.001011085
3:           REACTOME_INFLUENZA_VIRAL_RNA_TRANSCRIPTION_AND_REPLICATION     98      Down 0.003603039
4:                     REACTOME_3_UTR_MEDIATED_TRANSLATIONAL_REGULATION    103      Down 0.017458050
5: REACTOME_SRP_DEPENDENT_COTRANSLATIONAL_PROTEIN_TARGETING_TO_MEMBRANE    106      Down 0.017458050
6:                                                       MOOTHA_VOXPHOS     85      Down 0.030650877
#GSEA - c6
gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c6,0.05)
'select()' returned 1:many mapping between keys and columns
gsea[Direction=="Up",.(rn,NGenes,Direction,FDR)]
Empty data.table (0 rows) of 4 cols: rn,NGenes,Direction,FDR
gsea[Direction=="Down",.(rn,NGenes,Direction,FDR)]
Empty data.table (0 rows) of 4 cols: rn,NGenes,Direction,FDR
#ssGSEA - c6
ssGSEA.data <- ssGSEA.run(DE.data$v$E,Hs.c6,d,cont.matrix=cont.matrix)
'select()' returned 1:many mapping between keys and columns
Error in .local(expr, gset.idx.list, ...) : 
  unused argument (rnaseq = TRUE)

Only VHIO098 (w/ Selu) (Model: ~ PDX)

rr VHIO.OR <- subset.PDX(rnaseq,rnaseq\(meta[,PDX %in% c(\VHIO098\,\VHIO098OR\) & Treatment==\Selumetinib\ & merged.lanes==1]) model <- VHIO.OR\)meta[,PDX] d <- model.matrix(~ 0 + model) cont.matrix <- matrix(c(1,-1,rep(0,dim(d)[2]-2)), dim(d)[2], 1) colnames(cont.matrix) <- c(.minus.Naive) rownames(cont.matrix) <- colnames(d) cont.matrix

               OR.minus.Naive
modelVHIO098                1
modelVHIO098OR             -1

rr #Perform DE DE.data <- DE.run(VHIO.OR$human,d,2,cont.matrix = cont.matrix)

rr #Top DE genes table DE <- topTable.annotated.DE(DE.data$efit,p.val = 0.05)

'select()' returned 1:many mapping between keys and columns

rr if(nrow(DE)!=0){ table(DE[,direction]) DE[direction==.reg,.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)] DE[direction==.reg,.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)] #Pheatmap w/ batch correction i <- match(DE\(ENSEMBL,rownames(DE.data\)v\(E)) y <- DE.data\)v\(E[i,] labels.col <- rep(\\,nrow(VHIO.OR\)meta)) labels.row <- DE\(SYMBOL ann.col <- as.data.frame(VHIO.OR\)meta[,.(PDX)]) rownames(ann.col) <- VHIO.OR$meta[,Sample.name] pheatmap(y,labels_col=labels.col,labels_row=labels.row,annotation_col = ann.col,scale=) }

rr #GSEA - c2 gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c2,0.05)

'select()' returned 1:many mapping between keys and columns

rr gsea[Direction==,.(rn,NGenes,Direction,FDR)] r gsea[Direction==,.(rn,NGenes,Direction,FDR)]

rr #GSEA - c6 gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c6,0.05)

'select()' returned 1:many mapping between keys and columns

rr gsea[Direction==,.(rn,NGenes,Direction,FDR)]

rr gsea[Direction==,.(rn,NGenes,Direction,FDR)]

rr #ssGSEA - c6 ssGSEA.data <- ssGSEA.run(DE.data\(v\)E,Hs.c6,d,cont.matrix=cont.matrix)

'select()' returned 1:many mapping between keys and columns
The argument 'rnaseq' is deprecated and will be removed in the next release of GSVA. Please use the 'kcdf' argument instead.
Estimating GSVA scores for 189 gene sets.
Computing observed enrichment scores
Estimating ECDFs in microarray data with Gaussian kernels
Using parallel with 4 cores

  |                                                                                                                                                                  
  |                                                                                                                                                            |   0%

rr #Top DE gene.sets table ssGSEA <- topTable.annotated.ssGSEA(ssGSEA.data$efit)

No DE genes

rr if(nrow(ssGSEA)!=0){ ssGSEA[direction==.reg,.(direction,gene.set,adj.P.Val,logFC)] ssGSEA[direction==.reg,.(direction,gene.set,adj.P.Val,logFC)] } if(nrow(ssGSEA)>1){ #Pheatmap w/ batch correction i <- match(ssGSEA\(gene.set,rownames(ssGSEA.data\)w)) labels.col <- rep(\,nrow(VHIO.OR\(meta)) labels.row <- ssGSEA\)gene.set ann.col <- as.data.frame(HCI\(meta[,.(treatment)]) rownames(ann.col) <- HCI\)meta[,Sample.name] pheatmap(ssGSEA.data$w[i,],labels_col=labels.col,labels_row=labels.row,annotation_col = ann.col,scale=) }

Other models

Only STG139 (Model: ~ drug)

STG139 <- subset.PDX(rnaseq,rnaseq$meta[,PDX=="STG139" & merged.lanes==1])
treatment <- STG139$meta[,Treatment]
d <- model.matrix(~ 0 + treatment)

cont.matrix <- matrix(c(1,-1,rep(0,dim(d)[2]-2)), dim(d)[2], 1)
colnames(cont.matrix) <- c("Selu.minus.control")
rownames(cont.matrix) <- colnames(d)
cont.matrix

#Perform DE
DE.data <- DE.run(STG139$human,d,2,cont.matrix = cont.matrix)

#Top DE genes table
DE <- topTable.annotated.DE(DE.data$efit,p.val = 0.05)
if(nrow(DE)!=0){
  table(DE[,direction])
  DE[direction=="up.reg",.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)]
  DE[direction=="down.reg",.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)]

#Pheatmap w/ batch correction
  i <- match(DE$ENSEMBL,rownames(DE.data$v$E))
  y <- removeBatchEffect(DE.data$v$E[i,],design = model.matrix(~drug), batch= pdx)
  labels.col <- rep("",nrow(STG139$meta))
  labels.row <- DE$SYMBOL
  ann.col <- as.data.frame(STG139$meta[,.(pdx,drug)])
  rownames(ann.col) <- STG139$meta[,Sample.name]
  pheatmap(y,labels_col=labels.col,labels_row=labels.row,annotation_col = ann.col,scale="row")
}

#GSEA - c2
gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c2,0.05)
gsea[Direction=="Up",.(rn,NGenes,Direction,FDR)]
gsea[Direction=="Down",.(rn,NGenes,Direction,FDR)]

#GSEA - c6
gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c6,0.05)
gsea[Direction=="Up",.(rn,NGenes,Direction,FDR)]
gsea[Direction=="Down",.(rn,NGenes,Direction,FDR)]

#ssGSEA - c6
ssGSEA.data <- ssGSEA.run(DE.data$v$E,Hs.c6,d,cont.matrix=cont.matrix)

#Top DE gene.sets table
ssGSEA <- topTable.annotated.ssGSEA(ssGSEA.data$efit)
if(nrow(ssGSEA)!=0){
  ssGSEA[direction=="up.reg",.(direction,gene.set,adj.P.Val,logFC)]
  ssGSEA[direction=="down.reg",.(direction,gene.set,adj.P.Val,logFC)]
}

if(nrow(ssGSEA)>1){
  #Pheatmap w/ batch correction
  i <- match(ssGSEA$gene.set,rownames(ssGSEA.data$w))
  labels.col <- rep("",nrow(STG139$meta))
  labels.row <- ssGSEA$gene.set
  ann.col <- as.data.frame(HCI$meta[,.(treatment)])
  rownames(ann.col) <- HCI$meta[,Sample.name]
  pheatmap(ssGSEA.data$w[i,],labels_col=labels.col,labels_row=labels.row,annotation_col = ann.col,scale="row")
}

Only HCI009 (Model: ~ drug)

rr HCI <- subset.PDX(rnaseq,rnaseq\(meta[,PDX==\HCI009\]) treatment <- HCI\)meta[,Treatment] sequencing <- HCI$meta[,factor(merged.lanes)] d <- model.matrix(~ 0 + treatment + sequencing)

cont.matrix <- matrix(c(1,-1,rep(0,dim(d)[2]-2)), dim(d)[2], 1) colnames(cont.matrix) <- c(.minus.control) rownames(cont.matrix) <- colnames(d) cont.matrix

#Perform DE DE.data <- DE.run(HCI$human,d,2,cont.matrix = cont.matrix)

#Top DE genes table DE <- topTable.annotated.DE(DE.data$efit,p.val = 0.05) if(nrow(DE)!=0){ table(DE[,direction]) DE[direction==.reg,.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)] DE[direction==.reg,.(direction,ENSEMBL,SYMBOL,adj.P.Val,logFC)]

#Pheatmap w/ batch correction i <- match(DE\(ENSEMBL,rownames(DE.data\)v\(E)) y <- removeBatchEffect(DE.data\)v\(E[i,],design = model.matrix(~drug), batch= pdx) labels.col <- rep(\\,nrow(rnaseq\)meta)) labels.row <- DE\(SYMBOL ann.col <- as.data.frame(rnaseq\)meta[,.(pdx,drug)]) rownames(ann.col) <- rnaseq$meta[,Sample.name] pheatmap(y,labels_col=labels.col,labels_row=labels.row,annotation_col = ann.col,scale=) }

#GSEA - c2 gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c2,0.05) gsea[Direction==,.(rn,NGenes,Direction,FDR)] gsea[Direction==,.(rn,NGenes,Direction,FDR)]

#GSEA - c6 gsea <- GSEA.run(DE.data$v,d,cont.matrix[,1],Hs.c6,0.05) gsea[Direction==,.(rn,NGenes,Direction,FDR)] gsea[Direction==,.(rn,NGenes,Direction,FDR)]

#ssGSEA - c6 ssGSEA.data <- ssGSEA.run(DE.data\(v\)E,Hs.c6,d,cont.matrix=cont.matrix)

#Top DE gene.sets table ssGSEA <- topTable.annotated.ssGSEA(ssGSEA.data$efit) if(nrow(ssGSEA)!=0){ ssGSEA[direction==.reg,.(direction,gene.set,adj.P.Val,logFC)] ssGSEA[direction==.reg,.(direction,gene.set,adj.P.Val,logFC)] }

if(nrow(ssGSEA)>1){ #Pheatmap w/ batch correction i <- match(ssGSEA\(gene.set,rownames(ssGSEA.data\)w)) labels.col <- rep(\,nrow(HCI\(meta)) labels.row <- ssGSEA\)gene.set ann.col <- as.data.frame(HCI\(meta[,.(treatment)]) rownames(ann.col) <- HCI\)meta[,Sample.name] pheatmap(ssGSEA.data$w[i,],labels_col=labels.col,labels_row=labels.row,annotation_col = ann.col,scale=) }

LS0tCnRpdGxlOiAnUERYOiBEcnVnIHRyYWlscycKYXV0aG9yOiAiQWxpc3RhaXIgTWFydGluIgpkYXRlOiAnYHIgZm9ybWF0KFN5cy50aW1lKCksICJMYXN0IG1vZGlmaWVkOiAlZCAlYiAlWSIpYCcKb3V0cHV0OgogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKc3VidGl0bGU6IFNlbHUKbGF5b3V0OiBwYWdlCi0tLQoKIyBMb2FkIGxpYnJhcmllcyBhbmQgZGF0YQpgYGB7ciwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnJvb3QuZGlyIDwtICJ+L09uZURyaXZlL3Byb2plY3RzLyIKcHJvamVjdC5kaXIgPC0gcGFzdGUwKHJvb3QuZGlyLCJQRFgvIikKc291cmNlKHBhc3RlMChyb290LmRpciwiUi51dGlscy9STkFTRVEudXRpbHMuUiIpKQpzb3VyY2UocGFzdGUwKHByb2plY3QuZGlyLCJzcmMvbG9hZC5QRFguUiIpKQoKcm5hc2VxIDwtIGdldC5QRFgoKQptZXRhIDwtIGxvYWQubWV0YSgpCgptZXRhIDwtIHN1YnNldC5tZXRhKG1ldGEsbWV0YVsscHJvamVjdD09ImRydWcuc2VsdSJdKQpybmFzZXEgPC0gc3Vic2V0LlBEWChybmFzZXEsIHJuYXNlcSRtZXRhWyxTYW1wbGUubmFtZV0gJWluJSBtZXRhWyxTYW1wbGUubmFtZV0pCmBgYAoKIyBRQwoKYGBge3IsZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9Nn0KcmVhZC5kZXB0aC5wbG90cyhybmFzZXEkbWV0YSkKYGBgCgpXZSBzaG91bGQgcmVtb3ZlIHRoZSBydW5zIHRoYXQgY29udGFpbiB2ZXJ5IGZldyByZWFkcyBiZWZvcmUgd2UgbWVyZ2Ugb3RoZXJ3aXNlIHRoZXkgY291bGQgYmlhcyB0aGUgc3Vic2VxdWVudCBhbmFseXNpcy4gCgpgYGB7cn0Kcm5hc2VxIDwtIHN1YnNldC5QRFgocm5hc2VxLCBybmFzZXEkbWV0YVssaHVtYW4ubGlicmFyeS5zaXplPjFFNl0pCmBgYAoKUmVwZWF0IFFDIHBsb3RzOgoKYGBge3IsZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9Nn0KcmVhZC5kZXB0aC5wbG90cyhybmFzZXEkbWV0YSkKYGBgCgpgYGB7cn0Kcm5hc2VxIDwtIG1lcmdlLlBEWChybmFzZXEpCnJuYXNlcSRtZXRhIDwtIG1lcmdlKHJuYXNlcSRtZXRhLG1ldGEsc29ydD1GKQp1bmlxdWUocm5hc2VxJG1ldGFbLC4obWVyZ2VkLmxhbmVzLGFzLm51bWVyaWMoYXMuZmFjdG9yKG1lcmdlZC5sYW5lcykpKV0pCnJuYXNlcSRtZXRhWyxtZXJnZWQubGFuZXM6PWFzLm51bWVyaWMoYXMuZmFjdG9yKG1lcmdlZC5sYW5lcykpXQpgYGAKCldoYXQgc2FtcGxlcyByZW1haW4gYWZ0ZXIgYWxsIHRoYXQgUUM6CgpgYGB7cn0KdGFibGUodW5pcXVlKHJuYXNlcSRtZXRhWywuKFBEWCxUcmVhdG1lbnQsTW91c2UpXSlbLC4oUERYLFRyZWF0bWVudCldKQpgYGAKCk5vdGUgdGhhdCB0aGUgVkhJTzA5OCBzYW1wbGVzIGNvbnRhaW4gZHVwbGljYXRlcyAoYXMgbm90ZWQgYnkgbWljZSBudW1iZXJzKS4KCmBgYHtyfQpybmFzZXEkbWV0YVssLk4sLihNb3VzZSxQRFgsVHJlYXRtZW50KV1bTj4xXQpgYGAKCkxldCdzIHVzZSB0aGVzZSBkdXBsaWNhdGVzIHRvIHNlZSBpZiB0aGUgYXNzaWdubWVudCBvZiBodW1hbiBhbmQgbW91c2UgcmVhZHMgc3VmZmVyZWQgYnkgcmVkdWNpbmcgdG8gU0U1MCBzZXF1ZW5jaW5nIApOb3RlOiBtZXJnZWQubGFuZT09MSAtLT4gU0xYLTE0MDgyOyB3aGljaCBpcyBTRTUwKQoKYGBge3J9CnggPC0gcm5hc2VxJG1ldGFbTW91c2UgJWluJSBybmFzZXEkbWV0YVssLk4sLihNb3VzZSxQRFgsVHJlYXRtZW50KV1bTj4xLE1vdXNlXV1bb3JkZXIoTW91c2UpLC4oU2FtcGxlLm5hbWUsTW91c2UsbWVyZ2VkLmxhbmVzLG1vdXNlLmxpYnJhcnkuc2l6ZS8obW91c2UubGlicmFyeS5zaXplK2h1bWFuLmxpYnJhcnkuc2l6ZSkpXQpnZ3Bsb3QoeCkgKyBhZXMoeD1Nb3VzZSx5PVY0LGNvbG91cj1mYWN0b3IobWVyZ2VkLmxhbmVzKSkgKyBnZW9tX3BvaW50KHNpemU9NSkgKyB0aGVtZV93c2ooKSArIGNvb3JkX2ZsaXAoKQpgYGAKClRoZXJlIGRvZXMgbm90IGFwcGVhciB0byBiZSBhIHNpZ25pZmdhbnQgY2hhbmdlIGluIHRoZSBtb3VzZSBmcmFjdGlvbiBkdWUgdG8gc2VxdWVuY2luZy4gSG93ZXZlciwgbGFuZSA0IHRoYXQgd2hpY2ggY29udGFpbnMgYWxsIHRoZSBkdXBsaWNhdGVzIChuZXdzISksIGhhcyBjb25zaXN0YW50bHkgbG93ZXIgYW1vdW50cyBvZiBtb3VzZS4gSSBkbyBub3Qga25vdyB3aHkgYWxsIHRoZSBkdXBsaWNhdGVzIGFyZSBmb3VuZCB3aXRoaW4gU0xYLTE0OTA2LiBBcmUgYWxsIG9mIFNMWC0xNDkwNiBkdXBsaWNhdGVzPwoKYGBge3J9CnJuYXNlcSRtZXRhW01vdXNlICVpbiUgcm5hc2VxJG1ldGFbbWVyZ2VkLmxhbmVzPT00LE1vdXNlXV1bb3JkZXIoTW91c2UpLC4oU2FtcGxlLm5hbWUsbWVyZ2VkLmxhbmVzLFRyZWF0bWVudCxQcm9jZXNzaW5nLmJhdGNoKV0KYGBgCgpUaGVyZSBhcHBlYXJzIHRvIGJlIGR1cGxpY2F0aW9uIGRlcGVuZGluZyBvbiB0aGUgInByb2Nlc3NpbmcgYmF0Y2giLiBJIG5lZWQgdG8gY29uZmlybSB3aXRoIERpbWl0cmEgd2hhdCBleGFjdGx5IHRoaXMgd2FzIGluIHJlZmVyZW5jZSB0byBhbmQsIHBvdGVudGlhbGx5LCBmaWxsIGluIHRoZSAiTkFzIi4gVGhlIG1ldGEgZGF0YSB3b3VsZCBzdWdnZXN0IHRoYXQgYWxsIHRoZSAiTkFzIiBzaG91bGQgYmUgMS4KCi0tLT4gQWZ0ZXIgdGFsa2luZyB0byBEaW0sIEkgY2FuIGNvbmZpcm0gdGhhdCBhbGwgb2YgU0xYLTE0OTA2IGNvbnNpc3RlZCBvZiBzYW1wbGVzIHByb2Nlc3NlZCBpbiBhIGRpZmZlcmVudCBtYW5uZXIgdG8gdGhlIHJlc3QuIEZvciBlYXNlLCBsZXQgdXMgcmVtb3ZlIHRoZXNlIHNhbXBsZXMgZnJvbSB0aGUgYW5hbHlzaXMuCgpgYGB7cn0Kcm5hc2VxIDwtIHN1YnNldC5QRFgocm5hc2VxLHJuYXNlcSRtZXRhJG1lcmdlZC5sYW5lcyE9NCkKYGBgCgpMZXQgdXMgY2hlY2sgYWdhaW4gdGhlIG1vdXNlIGZyYWN0aW9ucyB3LnIudC4gYWxsIHNlcXVlbmNpbmcgcnVucy4gCgpgYGB7cn0KZ2dwbG90KHJuYXNlcSRtZXRhWywuKG1vdXNlLmxpYnJhcnkuc2l6ZS8obW91c2UubGlicmFyeS5zaXplK2h1bWFuLmxpYnJhcnkuc2l6ZSksbWVyZ2VkLmxhbmVzKV0pICsgYWVzKHg9ZmFjdG9yKG1lcmdlZC5sYW5lcyksIGZpbGwgPSBmYWN0b3IobWVyZ2VkLmxhbmVzKSwgeSA9IFYxKSArIGdlb21fYm94cGxvdCgpICsgZ2VvbV9qaXR0ZXIod2lkdGg9MC4xKQpgYGAKCkJvdGggb2YgdGhlIGFib3ZlIGluZGljYXRlIHRoYXQgd2UgaGF2ZSBub3QgbG9zdCBzZW5zaXRpdml0eSBpbiByZWR1Y2luZyB0aGUgb3VyIHJlYWQgbGVuZ3Rocy4KCgojIENlbGx1bGFyaXR5IGNoYW5nZXMKCkxldCdzIGp1c3Qgc2VlIHdoZXRoZXIgdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGluIHRoZSBQRFhzIGNlbGx1bGFyaXR5IGFzIHdlIHNhdyBjaGFuZ2VzIHdpdGggdGhlIE9sYXBhcmliIGRydWcgdHJlYXRtZW50LgoKYGBge3J9CnggPC0gbWVsdChybmFzZXEkbWV0YSxpZC52YXJzPWMoIlNhbXBsZS5uYW1lIiwiUERYIiwiVHJlYXRtZW50IiksbWVhc3VyZS52YXJzID0gYygibW91c2UubGlicmFyeS5zaXplIiwiaHVtYW4ubGlicmFyeS5zaXplIikpCnhbLHZhbHVlOj12YWx1ZS9zdW0odmFsdWUpLFNhbXBsZS5uYW1lXQpnZ3Bsb3QoeFt2YXJpYWJsZT09Im1vdXNlLmxpYnJhcnkuc2l6ZSJdKSArIGFlcyh4PVRyZWF0bWVudCx5PXZhbHVlLGZpbGw9VHJlYXRtZW50KSArIGdlb21fYm94cGxvdCgpICsgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEpKSArIGZhY2V0X3dyYXAoflBEWCxzY2FsZXMgPSAiZnJlZV95IikKYGBgCgpUaGVyZSBkb2VzIG5vdCBhcHBlYXIgdG8gYmUgYSBzeXN0ZW1hdGljIGNoYW5nZSBpbiB0aGUgY2VsbHVsYXJpdHkgd2l0aCB0cmVhdG1lbnQuIE5vdGUgdGhhdCBzZWx1IGlzIGEgZmFyIG1vcmUgdGFyZ2V0ZWQgdGhlcmFweSB0aGFuIG9sYXAsIGFuZCBoZW5jZSBtYXkgbm90IGNoYW5nZSB0aGUgc3Ryb21hLXR1bW9yIGZyYWN0aW9ucyBhcyBtdWNoLgoKIyBQQ0FzCgpgYGB7cn0KcGNhIDwtIHBjYS5ydW4ocm5hc2VxJGh1bWFuKQpwY2EgPC0gY2JpbmQocm5hc2VxJG1ldGEscGNhKQpwY2EkbWVyZ2VkLmxhbmVzIDwtIGZhY3RvcihwY2EkbWVyZ2VkLmxhbmVzKQpnZ3BhaXJzKHBjYSwgY29sdW1ucz1jKCdQQzEnLCAnUEMyJywgJ1BDMycsICJodW1hbi5saWJyYXJ5LnNpemUiKSxtYXBwaW5nPWFlcyhjb2xvcj1QRFgpLCB1cHBlcj1saXN0KGNvbnRpbnVvdXM9J2NvcicpKQpnZ3BhaXJzKHBjYSwgY29sdW1ucz1jKCdQQzEnLCAnUEMyJywgJ1BDMycsICJodW1hbi5saWJyYXJ5LnNpemUiKSxtYXBwaW5nPWFlcyhjb2xvcj1UcmVhdG1lbnQpLCB1cHBlcj1saXN0KGNvbnRpbnVvdXM9J2NvcicpKQpnZ3BhaXJzKHBjYSwgY29sdW1ucz1jKCdQQzEnLCAnUEMyJywgJ1BDMycsICJodW1hbi5saWJyYXJ5LnNpemUiKSxtYXBwaW5nPWFlcyhjb2xvcj1tZXJnZWQubGFuZXMpLCB1cHBlcj1saXN0KGNvbnRpbnVvdXM9J2NvcicpKSAgCmBgYAoKVGhlcmUgYXBwZWFycyBhIGxhcmdlIGJhdGNoIGVmZmVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIHNlcXVlbmNpbmcuIE91dHdpdGggb2YgdGhhdCB0aGVyZSBpcyBhbHNvIHNvbWUgZ3JvdXBpbmcgYmFzZWQgb24gcGR4IHR5cGUsIHdoaWxlIG5vdGhpbmcgbm90YWJsZSB3aXRoIHJlZ2FyZHMgdG8gdHJlYXRtZW50LgoKYGBge3J9CnJuYXNlcSRtZXRhWywuTiwuKG1lcmdlZC5sYW5lcyxQRFgsVHJlYXRtZW50KV1bb3JkZXIobWVyZ2VkLmxhbmVzKV0KYGBgCgpMZXQgdXMgcmVwZWF0IGJvdGggdGhlIGFib3ZlIFBDQXMgdXNpbmcgYmF0Y2ggY29ycmVjdGlvbiB0byBhY2NvdW50IGZvciB0aGUgc2VxdWVuY2luZy4KCmBgYHtyfQpwY2EgPC0gcGNhLnByZXAocm5hc2VxJGh1bWFuKQpwY2EgPC0gd2l0aChybmFzZXEkbWV0YSxyZW1vdmVCYXRjaEVmZmVjdChwY2EsZGVzaWduID0gbW9kZWwubWF0cml4KH4gUERYICsgVHJlYXRtZW50KSxiYXRjaCA9IG1lcmdlZC5sYW5lcykpCnBjYSA8LSBwcmNvbXAodChwY2EpLHNjYWxlPVQpCnN1bW1hcnkocGNhKQpwY2EgPC0gY2JpbmQocm5hc2VxJG1ldGEscGNhJHgpCnBjYSRtZXJnZWQubGFuZXMgPC0gZmFjdG9yKHBjYSRtZXJnZWQubGFuZXMpCmdncGFpcnMocGNhLCBjb2x1bW5zPWMoJ1BDMScsICdQQzInLCAnUEMzJywgImh1bWFuLmxpYnJhcnkuc2l6ZSIpLG1hcHBpbmc9YWVzKGNvbG9yPVBEWCksIHVwcGVyPWxpc3QoY29udGludW91cz0nY29yJykpCmdncGFpcnMocGNhLCBjb2x1bW5zPWMoJ1BDMScsICdQQzInLCAnUEMzJywgImh1bWFuLmxpYnJhcnkuc2l6ZSIpLG1hcHBpbmc9YWVzKGNvbG9yPVRyZWF0bWVudCksIHVwcGVyPWxpc3QoY29udGludW91cz0nY29yJykpCmdncGFpcnMocGNhLCBjb2x1bW5zPWMoJ1BDMScsICdQQzInLCAnUEMzJywgImh1bWFuLmxpYnJhcnkuc2l6ZSIpLG1hcHBpbmc9YWVzKGNvbG9yPW1lcmdlZC5sYW5lcyksIHVwcGVyPWxpc3QoY29udGludW91cz0nY29yJykpICAKYGBgCgpHaXZlbiB0aGUgY29uc3RydWN0aW9uIG9mIHRoZSBtZXRhIGRhdGEsIGl0J3MgaGFyZCB0byByZW1vdmUgdGhlIGVmZmVjdCBvZiB0aGUgc2VxdWVuY2luZyBmcm9tIHRoZSB2YXJpYWJsZXMgb2YgaW50ZXJlc3QuIEFzIHN1Y2gsIHdlIGdldCBvbmx5IGEgc21hbGwgcmVkdWN0aW9uIGluIHRoZSBzZXF1ZW5jaW5nIGRvbWluYXRpbmcgdGhlIHZhcmlhYmxpbGl0eS4KCkxldCdzIHBsb3QgdGhlIGRpZmZlcmVudCBQRFggYXJtcyBpbmRpdmlkdWFsbHkuCgpgYGB7cn0KZm9yKHBkeCBpbiB1bmlxdWUocm5hc2VxJG1ldGEkUERYKSl7CiAgeCA8LSBzdWJzZXQuUERYKHJuYXNlcSwgcm5hc2VxJG1ldGFbLHBkeCA9PSBQRFhdKQogIHBjYSA8LSBwY2EucnVuKHgkaHVtYW4pCiAgcGNhIDwtIGNiaW5kKHgkbWV0YSxwY2EpCiAgcGNhJG1lcmdlZC5sYW5lcyA8LSBmYWN0b3IocGNhJG1lcmdlZC5sYW5lcykKICBwcmludChnZ3BhaXJzKHBjYSwgY29sdW1ucz1jKCdQQzEnLCAnUEMyJywgJ1BDMycsICJodW1hbi5saWJyYXJ5LnNpemUiKSxtYXBwaW5nPWFlcyhjb2xvcj1UcmVhdG1lbnQsc2hhcGU9bWVyZ2VkLmxhbmVzKSwgdXBwZXI9bGlzdChjb250aW51b3VzPSdjb3InKSkgICsgZ2d0aXRsZShwZHgpKQp9CmBgYAoKCldlIGFyZSBidWdnZXJlZCBieSB0aGUgc2VxdWVuY2luZy4uLi4gOigKClNpbmNlIGl0cyBub3Qgb2J2aW91cyBieSB0aGUgZ3JvdXBpbmcsIHdoYXQgdGhlIHVua25vd24gc2FtcGxlIGlzIGZyb20sIEkgd2lsbCByZW1vdmUgaXQuCgpgYGB7cn0Kcm5hc2VxIDwtIHN1YnNldC5QRFgocm5hc2VxLHJuYXNlcSRtZXRhJFRyZWF0bWVudCE9IlVua25vd24iKQpgYGAKCiMgS2V5IHF1ZXN0aW9ucwoKKiBHZW5lcyBvZiBpbnRlcmVzdDogRUdGUiwgYXBvcHRvdGljIGdlbmVzIChiY2wyLCBtY2wxLCBiYXgpCiogQXJlIHRoZXJlIGFueSBzeXN0ZW1hdGljIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGNvbnRyb2wgYW5kIHRyZWF0ZWQgZ3JvdXBzPwoqIEFyZSB0aGVyZSBhbnkgdHJhaXRzL21hcmtlcnMgdGhhdCBkZWZpbmUgdGhlIHNwZWVkIHdpdGggd2hpY2ggcmVzaXN0YW5jZSBpcyBkZXZsb3BlZCBpbiB0aGUgdHJlYXRlZCBncm91cHM/CiogSXMgcmVzaXN0YW5jZSBkZXZlbG9wZWQgaW4gZGlmZmVyZW50IG1hbm5lcnMgYmV0d2VlbiB0aGUgdHJlYXRlZCBzYW1wbGVzPwoKIyBNb2RlbDogfiBkcnVnICsgcGR4CgojIyBBbGwgZGF0YQoKYGBge3J9CnNlcXVlbmNpbmcgPC0gcm5hc2VxJG1ldGFbLGZhY3RvcihtZXJnZWQubGFuZXMpXQp0cmVhdG1lbnQgPC0gcm5hc2VxJG1ldGFbLFRyZWF0bWVudF0KcGR4IDwtIHJuYXNlcSRtZXRhWyxQRFhdCmQgPC0gbW9kZWwubWF0cml4KH4gMCArIHRyZWF0bWVudCArIHBkeCArIHNlcXVlbmNpbmcpCgpjb250Lm1hdHJpeCA8LSBtYXRyaXgoYygxLC0xLHJlcCgwLGRpbShkKVsyXS0yKSksIGRpbShkKVsyXSwgMSkKY29sbmFtZXMoY29udC5tYXRyaXgpIDwtIGMoIlNlbHUubWludXMuY29udHJvbCIpCnJvd25hbWVzKGNvbnQubWF0cml4KSA8LSBjb2xuYW1lcyhkKQpjb250Lm1hdHJpeAoKI1BlcmZvcm0gREUKREUuZGF0YSA8LSBERS5ydW4ocm5hc2VxJGh1bWFuLGQsMixjb250Lm1hdHJpeCA9IGNvbnQubWF0cml4KQoKI1RvcCBERSBnZW5lcyB0YWJsZQpERSA8LSB0b3BUYWJsZS5hbm5vdGF0ZWQuREUoREUuZGF0YSRlZml0LHAudmFsID0gMC4wNSkKaWYobnJvdyhERSkhPTApewogIHRhYmxlKERFWyxkaXJlY3Rpb25dKQogIERFW2RpcmVjdGlvbj09InVwLnJlZyIsLihkaXJlY3Rpb24sRU5TRU1CTCxTWU1CT0wsYWRqLlAuVmFsLGxvZ0ZDKV0KICBERVtkaXJlY3Rpb249PSJkb3duLnJlZyIsLihkaXJlY3Rpb24sRU5TRU1CTCxTWU1CT0wsYWRqLlAuVmFsLGxvZ0ZDKV0KCiNQaGVhdG1hcCB3LyBiYXRjaCBjb3JyZWN0aW9uCiAgaSA8LSBtYXRjaChERSRFTlNFTUJMLHJvd25hbWVzKERFLmRhdGEkdiRFKSkKICB5IDwtIHJlbW92ZUJhdGNoRWZmZWN0KERFLmRhdGEkdiRFW2ksXSxkZXNpZ24gPSBtb2RlbC5tYXRyaXgofmRydWcpLCBiYXRjaD0gcGR4KQogIGxhYmVscy5jb2wgPC0gcmVwKCIiLG5yb3cocm5hc2VxJG1ldGEpKQogIGxhYmVscy5yb3cgPC0gREUkU1lNQk9MCiAgYW5uLmNvbCA8LSBhcy5kYXRhLmZyYW1lKHJuYXNlcSRtZXRhWywuKHBkeCxkcnVnKV0pCiAgcm93bmFtZXMoYW5uLmNvbCkgPC0gcm5hc2VxJG1ldGFbLFNhbXBsZS5uYW1lXQogIHBoZWF0bWFwKHksbGFiZWxzX2NvbD1sYWJlbHMuY29sLGxhYmVsc19yb3c9bGFiZWxzLnJvdyxhbm5vdGF0aW9uX2NvbCA9IGFubi5jb2wsc2NhbGU9InJvdyIpCn0KCiNHU0VBIC0gYzYKZ3NlYSA8LSBHU0VBLnJ1bihERS5kYXRhJHYsZCxjb250Lm1hdHJpeFssMV0sSHMuYzYsMC4wNSkKZ3NlYVtEaXJlY3Rpb249PSJVcCIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCmdzZWFbRGlyZWN0aW9uPT0iRG93biIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCgojR1NFQSAtIGMyCmdzZWEgPC0gR1NFQS5ydW4oREUuZGF0YSR2LGQsY29udC5tYXRyaXhbLDFdLEhzLmMyLDAuMDUpCmdzZWFbRGlyZWN0aW9uPT0iVXAiLC4ocm4sTkdlbmVzLERpcmVjdGlvbixGRFIpXQpnc2VhW0RpcmVjdGlvbj09IkRvd24iLC4ocm4sTkdlbmVzLERpcmVjdGlvbixGRFIpXQoKIyBzc0dTRUEKc3NHU0VBLmRhdGEgPC0gc3NHU0VBLnJ1bihERS5kYXRhJHYkRSxIcy5jNixkLGNvbnQubWF0cml4PWNvbnQubWF0cml4KQoKI1RvcCBERSBnZW5lLnNldHMgdGFibGUKc3NHU0VBIDwtIHRvcFRhYmxlLmFubm90YXRlZC5zc0dTRUEoc3NHU0VBLmRhdGEkZWZpdCkKaWYobnJvdyhzc0dTRUEpIT0wKXsKICBzc0dTRUFbZGlyZWN0aW9uPT0idXAucmVnIiwuKGRpcmVjdGlvbixnZW5lLnNldCxhZGouUC5WYWwsbG9nRkMpXQogIHNzR1NFQVtkaXJlY3Rpb249PSJkb3duLnJlZyIsLihkaXJlY3Rpb24sZ2VuZS5zZXQsYWRqLlAuVmFsLGxvZ0ZDKV0KICAKICAjUGhlYXRtYXAgdy8gYmF0Y2ggY29ycmVjdGlvbgogIGkgPC0gbWF0Y2goc3NHU0VBJGdlbmUuc2V0LHJvd25hbWVzKHNzR1NFQS5kYXRhJHcpKQogIHkgPC0gcmVtb3ZlQmF0Y2hFZmZlY3Qoc3NHU0VBLmRhdGEkd1tpLF0sZGVzaWduID0gbW9kZWwubWF0cml4KH5kcnVnKSwgYmF0Y2g9cGR4KQogIGxhYmVscy5jb2wgPC0gcmVwKCIiLG5yb3cocm5hc2VxJG1ldGEpKQogIGxhYmVscy5yb3cgPC0gc3NHU0VBJGdlbmUuc2V0CiAgYW5uLmNvbCA8LSBhcy5kYXRhLmZyYW1lKHJuYXNlcSRtZXRhWywuKHBkeCxkcnVnKV0pCiAgcm93bmFtZXMoYW5uLmNvbCkgPC0gcm5hc2VxJG1ldGFbLFNhbXBsZS5uYW1lXQogIHBoZWF0bWFwKHksbGFiZWxzX2NvbD1sYWJlbHMuY29sLGxhYmVsc19yb3c9bGFiZWxzLnJvdyxhbm5vdGF0aW9uX2NvbCA9IGFubi5jb2wsc2NhbGU9InJvdyIpCn0KYGBgCgpUaGUgbGFjayBvZiBhbnkgcmVzdWx0cyBpcyB1bnN1cHJpc2luZyBhcyB0aGlzIHN0YXRpc3RpY2FsIG1vZGVsIGlzIHRoZSBtb3N0IHNpbXBsaXN0aWM7IG5vdCBwcmVzdW1pbmcgdGhhdCBkaWZmZXJlbnQgbW9kZWxzIHJlYWN0IGRpZmZlcmVudGx5IHRvIHRoZSBkcnVnLCBlc3BjaWFsbHkgd2l0aCBhIHJlc2lzdGFudCBtb2RlbCBpbmNsdWRlZCwgaXMgZm9vbGlzaC4gQWxzbywgdGhlIHNlcXVlbmNpbmcgaXMgZG9taW5hdGluZyBhbGwgdGhlIHZhcmlhYmlsaXR5LgoKIyMjIEdlbmVzIG9mIEludGVyZXN0CgpUaGVzZSBnZW5lcyB3ZXJlIGZvdW5kIGluIHRoZSBzY1JOQXNlcSBkYXRhIHRvIGJlIG5vdGFibGU6CgoKYGBge3J9CmdlbmVzIDwtIGMoIktMRjQiLCAiSVJGMSIsICJORktCSUEiLCJDREtOMUEiLCJDRUJQRCIsIk1BUDNLOCIsIkVGTkExIikKaWRzIDwtIG1hcElkcyhvcmcuSHMuZWcuZGIsa2V5cz1nZW5lcyxrZXl0eXBlID0gIlNZTUJPTCIsY29sdW1uID0gIkVOU0VNQkwiLCBtdWx0aVZhbHMgPSAiZmlyc3QiKQp5IDwtIERFLmRhdGEkdiRFW21hdGNoKGlkcyxyb3duYW1lcyhERS5kYXRhJHYpKSxdCnJvd25hbWVzKHkpIDwtIGdlbmVzCnkgPC0gcmVtb3ZlQmF0Y2hFZmZlY3QoeSxkZXNpZ24gPSBtb2RlbC5tYXRyaXgofnRyZWF0bWVudCksIGJhdGNoPXBkeCwgYmF0Y2gyID0gc2VxdWVuY2luZykKCmZvcihpIGluIDE6bGVuZ3RoKGlkcykpewogIHggPC0geVtpLF0KICBzdHJpcGNoYXJ0KHh+dHJlYXRtZW50KnBkeCx2ZXJ0aWNhbD1UUlVFLGxhcz0yLGNleC5heGlzPTAuOCxwY2g9MTYsY29sPTE6MixtZXRob2Q9ImppdHRlciIsbWFpbj1nZW5lc1tpXSkKfQpgYGAKClNoaWZ0cyBvZiBtZWFuIHcuci50LiBQRFggbW9kZWxzCgpgYGB7cn0KeCA8LSBhcHBseSh5LDEsZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhieSh4LGludGVyYWN0aW9uKHRyZWF0bWVudCxwZHgpLG1lYW4pKSkKeCA8LSB4W3NlcSgxLGJ5PTIsbGVuZ3RoLm91dCA9IGxlbmd0aCh1bmlxdWUocGR4KSkpLF0gLSB4W3NlcSgyLGJ5PTIsbGVuZ3RoLm91dCA9IGxlbmd0aCh1bmlxdWUocGR4KSkpLF0Kcm93bmFtZXMoeCkgPC0gc29ydCh1bmlxdWUocGR4KSkKeCA8LSBhcy5kYXRhLnRhYmxlKG1lbHQoeCkpCmdncGxvdCh4KSArIGFlcyh4PVZhcjEseT12YWx1ZSkgKyBnZW9tX2NvbCgpICsgZmFjZXRfd3JhcCh+VmFyMikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKYGBgCgpSZXBlYXQgYWJvdmUgd2l0aCBtZWRpYW4gKGxlc3MgYWZmZWN0ZWQgYnkgb3V0bGllcnMpCgpgYGB7cn0KeCA8LSBhcHBseSh5LDEsZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhieSh4LGludGVyYWN0aW9uKHRyZWF0bWVudCxwZHgpLG1lZGlhbikpKQp4IDwtIHhbc2VxKDEsYnk9MixsZW5ndGgub3V0ID0gbGVuZ3RoKHVuaXF1ZShwZHgpKSksXSAtIHhbc2VxKDIsYnk9MixsZW5ndGgub3V0ID0gbGVuZ3RoKHVuaXF1ZShwZHgpKSksXQpyb3duYW1lcyh4KSA8LSBzb3J0KHVuaXF1ZShwZHgpKQp4IDwtIGFzLmRhdGEudGFibGUobWVsdCh4KSkKZ2dwbG90KHgpICsgYWVzKHg9VmFyMSx5PXZhbHVlKSArIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH5WYXIyKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpgYGAKCiMjIyBQYXRod2F5cyBvZiBpbnRlcmVzdAoKTGV0IHVzIGFsc28gY2hlY2sgdGhlIExFRjEgc2lnbmF0dXJlLCB3aGljaCBzaG93ZWQgYSByZXNwb25zZSBpbiB0aGUgc2NSTkEtc2VxIGRhdGEgYmV0d2VlbiByZXNwb25zZSBhbmQgcmVzaXN0ZW5jZSBzYW1wbGVzOyBhIGNvbXBhcmlzb24gd2UgY2FuJ3QgcGVyZm9ybSBkdWUgdG8gc2FtcGxlIG51bWJlcnMuCgpgYGB7cn0KcGF0aHdheXMgPC0gYygiTEVGMV9VUC5WMV9VUCIsICJTTkY1X0ROLlYxX1VQIiwgIk1FS19VUC5WMV9ETiIpCnkgPC0gc3NHU0VBLmRhdGEkd1ttYXRjaChwYXRod2F5cyxyb3duYW1lcyhzc0dTRUEuZGF0YSR3KSksXQp5IDwtIHJlbW92ZUJhdGNoRWZmZWN0KHksZGVzaWduID0gbW9kZWwubWF0cml4KH50cmVhdG1lbnQpLCBiYXRjaD1wZHgsIGJhdGNoMiA9IHNlcXVlbmNpbmcpCmZvcihpIGluIDE6bGVuZ3RoKHBhdGh3YXlzKSl7CiAgeCA8LSB5W2ksXQogIHN0cmlwY2hhcnQoeH50cmVhdG1lbnQqcGR4LHZlcnRpY2FsPVRSVUUsbGFzPTIsY2V4LmF4aXM9MC44LHBjaD0xNixjb2w9MToyLG1ldGhvZD0iaml0dGVyIixtYWluPXBhdGh3YXlzW2ldKQp9CmBgYAoKClNoaWZ0cyBvZiBtZWFuIHcuci50LiBQRFggbW9kZWxzCgpgYGB7cn0KeCA8LSBhcHBseSh5LDEsZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhieSh4LGludGVyYWN0aW9uKHRyZWF0bWVudCxwZHgpLG1lYW4pKSkKeCA8LSB4W3NlcSgxLGJ5PTIsbGVuZ3RoLm91dCA9IGxlbmd0aCh1bmlxdWUocGR4KSkpLF0gLSB4W3NlcSgyLGJ5PTIsbGVuZ3RoLm91dCA9IGxlbmd0aCh1bmlxdWUocGR4KSkpLF0Kcm93bmFtZXMoeCkgPC0gc29ydCh1bmlxdWUocGR4KSkKeCA8LSBhcy5kYXRhLnRhYmxlKG1lbHQoeCkpCmdncGxvdCh4KSArIGFlcyh4PVZhcjEseT12YWx1ZSkgKyBnZW9tX2NvbCgpICsgZmFjZXRfd3JhcCh+VmFyMikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKYGBgCgpSZXBlYXQgYWJvdmUgd2l0aCBtZWRpYW4gKGxlc3MgYWZmZWN0ZWQgYnkgb3V0bGllcnMpCgpgYGB7cn0KeCA8LSBhcHBseSh5LDEsZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhieSh4LGludGVyYWN0aW9uKHRyZWF0bWVudCxwZHgpLG1lZGlhbikpKQp4IDwtIHhbc2VxKDEsYnk9MixsZW5ndGgub3V0ID0gbGVuZ3RoKHVuaXF1ZShwZHgpKSksXSAtIHhbc2VxKDIsYnk9MixsZW5ndGgub3V0ID0gbGVuZ3RoKHVuaXF1ZShwZHgpKSksXQpyb3duYW1lcyh4KSA8LSBzb3J0KHVuaXF1ZShwZHgpKQp4IDwtIGFzLmRhdGEudGFibGUobWVsdCh4KSkKZ2dwbG90KHgpICsgYWVzKHg9VmFyMSx5PXZhbHVlKSArIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH5WYXIyKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpgYGAKCiMgTW9kZWw6IH4gZHJ1ZzpwZHgKCmBgYHtyfQpzZXF1ZW5jaW5nIDwtIHJuYXNlcSRtZXRhWyxmYWN0b3IobWVyZ2VkLmxhbmVzKV0KdHJlYXRtZW50IDwtIHJuYXNlcSRtZXRhWyxUcmVhdG1lbnRdCnBkeCA8LSBybmFzZXEkbWV0YVssUERYXQoKZCA8LSBtb2RlbC5tYXRyaXgofiAwICsgc2VxdWVuY2luZyArIHRyZWF0bWVudDpwZHgpCmQgPC0gZFssY29sU3VtcyhkKSE9MF0KZCA8LSBkWywhKGNvbG5hbWVzKGQpICVpbiUgYygic2VxdWVuY2luZzMiKSldCgpjIDwtIG1hdHJpeCgwLGRpbShkKVsyXSxsZW5ndGgodW5pcXVlKHBkeCkpKQpjW2NiaW5kKHNlcSgxLGJ5PTIsbGVuZ3RoLm91dD1sZW5ndGgodW5pcXVlKHBkeCkpKSArIChsZW5ndGgobGV2ZWxzKHNlcXVlbmNpbmcpKS0xKSwxOmxlbmd0aCh1bmlxdWUocGR4KSkpXSA8LSAxCmNbY2JpbmQoc2VxKDIsYnk9MixsZW5ndGgub3V0PWxlbmd0aCh1bmlxdWUocGR4KSkpICsgKGxlbmd0aChsZXZlbHMoc2VxdWVuY2luZykpLTEpLDE6bGVuZ3RoKHVuaXF1ZShwZHgpKSldIDwtIC0xCmNvbG5hbWVzKGMpIDwtIHBhc3RlKHNvcnQodW5pcXVlKHBkeCkpLCJTZWx1Lm1pbnVzLmNvbnRyb2wiLHNlcD0iOiIpCnJvd25hbWVzKGMpIDwtIGNvbG5hbWVzKGQpCmMKCkRFLmRhdGEgPC0gREUucnVuKHJuYXNlcSRodW1hbixkLDIsY29udC5tYXRyaXggPSBjKQoKI1RhYmxlIG9mIERFIGdlbmVzCkRFIDwtIGRlY2lkZVRlc3QuYW5ub3RhdGVkLkRFKERFLmRhdGEkZWZpdCxwLnZhbCA9IDAuMDUpCkRFCgojVmVubkRpYWdybXMgb2YgREUgZ2VuZXMKaWYobnJvdyhERSkhPTApIHZlbm5EaWFncmFtLnBhaXJlZChERVssMjo2XSkKYGBgCgojIFZISU8wOTgKIyMgT25seSBWSElPMDk4LW5haXZlIChNb2RlbDogfiBkcnVnKQoKYGBge3J9ClZISSA8LSBzdWJzZXQuUERYKHJuYXNlcSxybmFzZXEkbWV0YVssUERYPT0iVkhJTzA5OCIgJiBUcmVhdG1lbnQhPSJVbmtub3duIl0pCnRyZWF0bWVudCA8LSBWSEkkbWV0YVssVHJlYXRtZW50XQpzZXF1ZW5jaW5nIDwtIFZISSRtZXRhWyxmYWN0b3IobWVyZ2VkLmxhbmVzKV0KI2QgPC0gbW9kZWwubWF0cml4KH4gMCArIHRyZWF0bWVudCArIHNlcXVlbmNpbmcpCmQgPC0gbW9kZWwubWF0cml4KH4gMCArIHRyZWF0bWVudCkgIzwtIEJhZCBBbGkKCgpjb250Lm1hdHJpeCA8LSBtYXRyaXgoYygxLC0xLHJlcCgwLGRpbShkKVsyXS0yKSksIGRpbShkKVsyXSwgMSkKY29sbmFtZXMoY29udC5tYXRyaXgpIDwtIGMoIlNlbHUubWludXMuY29udHJvbCIpCnJvd25hbWVzKGNvbnQubWF0cml4KSA8LSBjb2xuYW1lcyhkKQpjb250Lm1hdHJpeAoKI1BlcmZvcm0gREUKREUuZGF0YSA8LSBERS5ydW4oVkhJJGh1bWFuLGQsMixjb250Lm1hdHJpeCA9IGNvbnQubWF0cml4KQoKI1RvcCBERSBnZW5lcyB0YWJsZQpERSA8LSB0b3BUYWJsZS5hbm5vdGF0ZWQuREUoREUuZGF0YSRlZml0LHAudmFsID0gMC41KQppZihucm93KERFKSE9MCl7CiAgdGFibGUoREVbLGRpcmVjdGlvbl0pCiAgREVbZGlyZWN0aW9uPT0idXAucmVnIiwuKGRpcmVjdGlvbixFTlNFTUJMLFNZTUJPTCxhZGouUC5WYWwsbG9nRkMpXQogIERFW2RpcmVjdGlvbj09ImRvd24ucmVnIiwuKGRpcmVjdGlvbixFTlNFTUJMLFNZTUJPTCxhZGouUC5WYWwsbG9nRkMpXQoKI1BoZWF0bWFwIHcvIGJhdGNoIGNvcnJlY3Rpb24KICBpIDwtIG1hdGNoKERFJEVOU0VNQkwscm93bmFtZXMoREUuZGF0YSR2JEUpKQogIHkgPC0gcmVtb3ZlQmF0Y2hFZmZlY3QoREUuZGF0YSR2JEVbaSxdLGRlc2lnbiA9IG1vZGVsLm1hdHJpeCh+ZHJ1ZyksIGJhdGNoPSBwZHgpCiAgbGFiZWxzLmNvbCA8LSByZXAoIiIsbnJvdyhybmFzZXEkbWV0YSkpCiAgbGFiZWxzLnJvdyA8LSBERSRTWU1CT0wKICBhbm4uY29sIDwtIGFzLmRhdGEuZnJhbWUocm5hc2VxJG1ldGFbLC4ocGR4LGRydWcpXSkKICByb3duYW1lcyhhbm4uY29sKSA8LSBybmFzZXEkbWV0YVssU2FtcGxlLm5hbWVdCiAgcGhlYXRtYXAoeSxsYWJlbHNfY29sPWxhYmVscy5jb2wsbGFiZWxzX3Jvdz1sYWJlbHMucm93LGFubm90YXRpb25fY29sID0gYW5uLmNvbCxzY2FsZT0icm93IikKfQoKI0dTRUEgLSBjMgpnc2VhIDwtIEdTRUEucnVuKERFLmRhdGEkdixkLGNvbnQubWF0cml4WywxXSxIcy5jMiwwLjA1KQpnc2VhW0RpcmVjdGlvbj09IlVwIiwuKHJuLE5HZW5lcyxEaXJlY3Rpb24sRkRSKV0KZ3NlYVtEaXJlY3Rpb249PSJEb3duIiwuKHJuLE5HZW5lcyxEaXJlY3Rpb24sRkRSKV0KCiNHU0VBIC0gYzYKZ3NlYSA8LSBHU0VBLnJ1bihERS5kYXRhJHYsZCxjb250Lm1hdHJpeFssMV0sSHMuYzYsMC4wNSkKZ3NlYVtEaXJlY3Rpb249PSJVcCIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCmdzZWFbRGlyZWN0aW9uPT0iRG93biIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCgojc3NHU0VBIC0gYzYKc3NHU0VBLmRhdGEgPC0gc3NHU0VBLnJ1bihERS5kYXRhJHYkRSxIcy5jNixkLGNvbnQubWF0cml4PWNvbnQubWF0cml4KQoKI1RvcCBERSBnZW5lLnNldHMgdGFibGUKc3NHU0VBIDwtIHRvcFRhYmxlLmFubm90YXRlZC5zc0dTRUEoc3NHU0VBLmRhdGEkZWZpdCkKaWYobnJvdyhzc0dTRUEpIT0wKXsKICBzc0dTRUFbZGlyZWN0aW9uPT0idXAucmVnIiwuKGRpcmVjdGlvbixnZW5lLnNldCxhZGouUC5WYWwsbG9nRkMpXQogIHNzR1NFQVtkaXJlY3Rpb249PSJkb3duLnJlZyIsLihkaXJlY3Rpb24sZ2VuZS5zZXQsYWRqLlAuVmFsLGxvZ0ZDKV0KfQoKaWYobnJvdyhzc0dTRUEpPjEpewogICNQaGVhdG1hcCB3LyBiYXRjaCBjb3JyZWN0aW9uCiAgaSA8LSBtYXRjaChzc0dTRUEkZ2VuZS5zZXQscm93bmFtZXMoc3NHU0VBLmRhdGEkdykpCiAgbGFiZWxzLmNvbCA8LSByZXAoIiIsbnJvdyhWSEkkbWV0YSkpCiAgbGFiZWxzLnJvdyA8LSBzc0dTRUEkZ2VuZS5zZXQKICBhbm4uY29sIDwtIGFzLmRhdGEuZnJhbWUoVkhJJG1ldGFbLC4odHJlYXRtZW50KV0pCiAgcm93bmFtZXMoYW5uLmNvbCkgPC0gVkhJJG1ldGFbLFNhbXBsZS5uYW1lXQogIHBoZWF0bWFwKHNzR1NFQS5kYXRhJHdbaSxdLGxhYmVsc19jb2w9bGFiZWxzLmNvbCxsYWJlbHNfcm93PWxhYmVscy5yb3csYW5ub3RhdGlvbl9jb2wgPSBhbm4uY29sLHNjYWxlPSJyb3ciKQp9CmBgYAoKIyMgT25seSBWSElPMDk4T1IgKE1vZGVsOiB+IGRydWcpCgpgYGB7cn0KVkhJTy5PUiA8LSBzdWJzZXQuUERYKHJuYXNlcSxybmFzZXEkbWV0YVssUERYPT0iVkhJTzA5OE9SIl0pCnRyZWF0bWVudCA8LSBWSElPLk9SJG1ldGFbLFRyZWF0bWVudF0KZCA8LSBtb2RlbC5tYXRyaXgofiAwICsgdHJlYXRtZW50KQoKY29udC5tYXRyaXggPC0gbWF0cml4KGMoMSwtMSxyZXAoMCxkaW0oZClbMl0tMikpLCBkaW0oZClbMl0sIDEpCmNvbG5hbWVzKGNvbnQubWF0cml4KSA8LSBjKCJTZWx1Lm1pbnVzLmNvbnRyb2wiKQpyb3duYW1lcyhjb250Lm1hdHJpeCkgPC0gY29sbmFtZXMoZCkKY29udC5tYXRyaXgKCiNQZXJmb3JtIERFCkRFLmRhdGEgPC0gREUucnVuKFZISU8uT1IkaHVtYW4sZCwyLGNvbnQubWF0cml4ID0gY29udC5tYXRyaXgpCgojVG9wIERFIGdlbmVzIHRhYmxlCkRFIDwtIHRvcFRhYmxlLmFubm90YXRlZC5ERShERS5kYXRhJGVmaXQscC52YWwgPSAwLjA1KQppZihucm93KERFKSE9MCl7CiAgdGFibGUoREVbLGRpcmVjdGlvbl0pCiAgREVbZGlyZWN0aW9uPT0idXAucmVnIiwuKGRpcmVjdGlvbixFTlNFTUJMLFNZTUJPTCxhZGouUC5WYWwsbG9nRkMpXQogIERFW2RpcmVjdGlvbj09ImRvd24ucmVnIiwuKGRpcmVjdGlvbixFTlNFTUJMLFNZTUJPTCxhZGouUC5WYWwsbG9nRkMpXQoKI1BoZWF0bWFwIHcvIGJhdGNoIGNvcnJlY3Rpb24KICBpIDwtIG1hdGNoKERFJEVOU0VNQkwscm93bmFtZXMoREUuZGF0YSR2JEUpKQogIHkgPC0gcmVtb3ZlQmF0Y2hFZmZlY3QoREUuZGF0YSR2JEVbaSxdLGRlc2lnbiA9IG1vZGVsLm1hdHJpeCh+ZHJ1ZyksIGJhdGNoPSBwZHgpCiAgbGFiZWxzLmNvbCA8LSByZXAoIiIsbnJvdyhWSElPLk9SJG1ldGEpKQogIGxhYmVscy5yb3cgPC0gREUkU1lNQk9MCiAgYW5uLmNvbCA8LSBhcy5kYXRhLmZyYW1lKFZISU8uT1IkbWV0YVssLihwZHgsZHJ1ZyldKQogIHJvd25hbWVzKGFubi5jb2wpIDwtIFZISU8uT1IkbWV0YVssU2FtcGxlLm5hbWVdCiAgcGhlYXRtYXAoeSxsYWJlbHNfY29sPWxhYmVscy5jb2wsbGFiZWxzX3Jvdz1sYWJlbHMucm93LGFubm90YXRpb25fY29sID0gYW5uLmNvbCxzY2FsZT0icm93IikKfQoKI0dTRUEgLSBjMgpnc2VhIDwtIEdTRUEucnVuKERFLmRhdGEkdixkLGNvbnQubWF0cml4WywxXSxIcy5jMiwwLjA1KQpnc2VhW0RpcmVjdGlvbj09IlVwIiwuKHJuLE5HZW5lcyxEaXJlY3Rpb24sRkRSKV0KZ3NlYVtEaXJlY3Rpb249PSJEb3duIiwuKHJuLE5HZW5lcyxEaXJlY3Rpb24sRkRSKV0KCiNHU0VBIC0gYzYKZ3NlYSA8LSBHU0VBLnJ1bihERS5kYXRhJHYsZCxjb250Lm1hdHJpeFssMV0sSHMuYzYsMC4wNSkKZ3NlYVtEaXJlY3Rpb249PSJVcCIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCmdzZWFbRGlyZWN0aW9uPT0iRG93biIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCgojc3NHU0VBIC0gYzYKc3NHU0VBLmRhdGEgPC0gc3NHU0VBLnJ1bihERS5kYXRhJHYkRSxIcy5jNixkLGNvbnQubWF0cml4PWNvbnQubWF0cml4KQoKI1RvcCBERSBnZW5lLnNldHMgdGFibGUKc3NHU0VBIDwtIHRvcFRhYmxlLmFubm90YXRlZC5zc0dTRUEoc3NHU0VBLmRhdGEkZWZpdCkKaWYobnJvdyhzc0dTRUEpIT0wKXsKICBzc0dTRUFbZGlyZWN0aW9uPT0idXAucmVnIiwuKGRpcmVjdGlvbixnZW5lLnNldCxhZGouUC5WYWwsbG9nRkMpXQogIHNzR1NFQVtkaXJlY3Rpb249PSJkb3duLnJlZyIsLihkaXJlY3Rpb24sZ2VuZS5zZXQsYWRqLlAuVmFsLGxvZ0ZDKV0KfQoKaWYobnJvdyhzc0dTRUEpPjEpewogICNQaGVhdG1hcCB3LyBiYXRjaCBjb3JyZWN0aW9uCiAgaSA8LSBtYXRjaChzc0dTRUEkZ2VuZS5zZXQscm93bmFtZXMoc3NHU0VBLmRhdGEkdykpCiAgbGFiZWxzLmNvbCA8LSByZXAoIiIsbnJvdyhWSElPLk9SJG1ldGEpKQogIGxhYmVscy5yb3cgPC0gc3NHU0VBJGdlbmUuc2V0CiAgYW5uLmNvbCA8LSBhcy5kYXRhLmZyYW1lKEhDSSRtZXRhWywuKHRyZWF0bWVudCldKQogIHJvd25hbWVzKGFubi5jb2wpIDwtIEhDSSRtZXRhWyxTYW1wbGUubmFtZV0KICBwaGVhdG1hcChzc0dTRUEuZGF0YSR3W2ksXSxsYWJlbHNfY29sPWxhYmVscy5jb2wsbGFiZWxzX3Jvdz1sYWJlbHMucm93LGFubm90YXRpb25fY29sID0gYW5uLmNvbCxzY2FsZT0icm93IikKfQpgYGAKCiMjIE9ubHkgVkhJTzA5OCAody8gU2VsdSkgKE1vZGVsOiB+IFBEWCkKCmBgYHtyfQpWSElPLk9SIDwtIHN1YnNldC5QRFgocm5hc2VxLHJuYXNlcSRtZXRhWyxQRFggJWluJSBjKCJWSElPMDk4IiwiVkhJTzA5OE9SIikgJiBUcmVhdG1lbnQ9PSJTZWx1bWV0aW5pYiIgJiBtZXJnZWQubGFuZXM9PTFdKQptb2RlbCA8LSBWSElPLk9SJG1ldGFbLFBEWF0KZCA8LSBtb2RlbC5tYXRyaXgofiAwICsgbW9kZWwpCgpjb250Lm1hdHJpeCA8LSBtYXRyaXgoYygxLC0xLHJlcCgwLGRpbShkKVsyXS0yKSksIGRpbShkKVsyXSwgMSkKY29sbmFtZXMoY29udC5tYXRyaXgpIDwtIGMoIk9SLm1pbnVzLk5haXZlIikKcm93bmFtZXMoY29udC5tYXRyaXgpIDwtIGNvbG5hbWVzKGQpCmNvbnQubWF0cml4CgojUGVyZm9ybSBERQpERS5kYXRhIDwtIERFLnJ1bihWSElPLk9SJGh1bWFuLGQsMixjb250Lm1hdHJpeCA9IGNvbnQubWF0cml4KQoKI1RvcCBERSBnZW5lcyB0YWJsZQpERSA8LSB0b3BUYWJsZS5hbm5vdGF0ZWQuREUoREUuZGF0YSRlZml0LHAudmFsID0gMC4wNSkKaWYobnJvdyhERSkhPTApewogIHRhYmxlKERFWyxkaXJlY3Rpb25dKQogIERFW2RpcmVjdGlvbj09InVwLnJlZyIsLihkaXJlY3Rpb24sRU5TRU1CTCxTWU1CT0wsYWRqLlAuVmFsLGxvZ0ZDKV0KICBERVtkaXJlY3Rpb249PSJkb3duLnJlZyIsLihkaXJlY3Rpb24sRU5TRU1CTCxTWU1CT0wsYWRqLlAuVmFsLGxvZ0ZDKV0KCiNQaGVhdG1hcCB3LyBiYXRjaCBjb3JyZWN0aW9uCiAgaSA8LSBtYXRjaChERSRFTlNFTUJMLHJvd25hbWVzKERFLmRhdGEkdiRFKSkKICB5IDwtIERFLmRhdGEkdiRFW2ksXQogIGxhYmVscy5jb2wgPC0gcmVwKCIiLG5yb3coVkhJTy5PUiRtZXRhKSkKICBsYWJlbHMucm93IDwtIERFJFNZTUJPTAogIGFubi5jb2wgPC0gYXMuZGF0YS5mcmFtZShWSElPLk9SJG1ldGFbLC4oUERYKV0pCiAgcm93bmFtZXMoYW5uLmNvbCkgPC0gVkhJTy5PUiRtZXRhWyxTYW1wbGUubmFtZV0KICBwaGVhdG1hcCh5LGxhYmVsc19jb2w9bGFiZWxzLmNvbCxsYWJlbHNfcm93PWxhYmVscy5yb3csYW5ub3RhdGlvbl9jb2wgPSBhbm4uY29sLHNjYWxlPSJyb3ciKQp9CgojR1NFQSAtIGMyCmdzZWEgPC0gR1NFQS5ydW4oREUuZGF0YSR2LGQsY29udC5tYXRyaXhbLDFdLEhzLmMyLDAuMDUpCmdzZWFbRGlyZWN0aW9uPT0iVXAiLC4ocm4sTkdlbmVzLERpcmVjdGlvbixGRFIpXQpnc2VhW0RpcmVjdGlvbj09IkRvd24iLC4ocm4sTkdlbmVzLERpcmVjdGlvbixGRFIpXQoKI0dTRUEgLSBjNgpnc2VhIDwtIEdTRUEucnVuKERFLmRhdGEkdixkLGNvbnQubWF0cml4WywxXSxIcy5jNiwwLjA1KQpnc2VhW0RpcmVjdGlvbj09IlVwIiwuKHJuLE5HZW5lcyxEaXJlY3Rpb24sRkRSKV0KZ3NlYVtEaXJlY3Rpb249PSJEb3duIiwuKHJuLE5HZW5lcyxEaXJlY3Rpb24sRkRSKV0KCiNzc0dTRUEgLSBjNgpzc0dTRUEuZGF0YSA8LSBzc0dTRUEucnVuKERFLmRhdGEkdiRFLEhzLmM2LGQsY29udC5tYXRyaXg9Y29udC5tYXRyaXgpCgojVG9wIERFIGdlbmUuc2V0cyB0YWJsZQpzc0dTRUEgPC0gdG9wVGFibGUuYW5ub3RhdGVkLnNzR1NFQShzc0dTRUEuZGF0YSRlZml0KQppZihucm93KHNzR1NFQSkhPTApewogIHNzR1NFQVtkaXJlY3Rpb249PSJ1cC5yZWciLC4oZGlyZWN0aW9uLGdlbmUuc2V0LGFkai5QLlZhbCxsb2dGQyldCiAgc3NHU0VBW2RpcmVjdGlvbj09ImRvd24ucmVnIiwuKGRpcmVjdGlvbixnZW5lLnNldCxhZGouUC5WYWwsbG9nRkMpXQp9CgppZihucm93KHNzR1NFQSk+MSl7CiAgI1BoZWF0bWFwIHcvIGJhdGNoIGNvcnJlY3Rpb24KICBpIDwtIG1hdGNoKHNzR1NFQSRnZW5lLnNldCxyb3duYW1lcyhzc0dTRUEuZGF0YSR3KSkKICBsYWJlbHMuY29sIDwtIHJlcCgiIixucm93KFZISU8uT1IkbWV0YSkpCiAgbGFiZWxzLnJvdyA8LSBzc0dTRUEkZ2VuZS5zZXQKICBhbm4uY29sIDwtIGFzLmRhdGEuZnJhbWUoSENJJG1ldGFbLC4odHJlYXRtZW50KV0pCiAgcm93bmFtZXMoYW5uLmNvbCkgPC0gSENJJG1ldGFbLFNhbXBsZS5uYW1lXQogIHBoZWF0bWFwKHNzR1NFQS5kYXRhJHdbaSxdLGxhYmVsc19jb2w9bGFiZWxzLmNvbCxsYWJlbHNfcm93PWxhYmVscy5yb3csYW5ub3RhdGlvbl9jb2wgPSBhbm4uY29sLHNjYWxlPSJyb3ciKQp9CmBgYAoKIyBPdGhlciBtb2RlbHMKCiMjIE9ubHkgU1RHMTM5IChNb2RlbDogfiBkcnVnKQoKYGBge3J9ClNURzEzOSA8LSBzdWJzZXQuUERYKHJuYXNlcSxybmFzZXEkbWV0YVssUERYPT0iU1RHMTM5IiAmIG1lcmdlZC5sYW5lcz09MV0pCnRyZWF0bWVudCA8LSBTVEcxMzkkbWV0YVssVHJlYXRtZW50XQpkIDwtIG1vZGVsLm1hdHJpeCh+IDAgKyB0cmVhdG1lbnQpCgpjb250Lm1hdHJpeCA8LSBtYXRyaXgoYygxLC0xLHJlcCgwLGRpbShkKVsyXS0yKSksIGRpbShkKVsyXSwgMSkKY29sbmFtZXMoY29udC5tYXRyaXgpIDwtIGMoIlNlbHUubWludXMuY29udHJvbCIpCnJvd25hbWVzKGNvbnQubWF0cml4KSA8LSBjb2xuYW1lcyhkKQpjb250Lm1hdHJpeAoKI1BlcmZvcm0gREUKREUuZGF0YSA8LSBERS5ydW4oU1RHMTM5JGh1bWFuLGQsMixjb250Lm1hdHJpeCA9IGNvbnQubWF0cml4KQoKI1RvcCBERSBnZW5lcyB0YWJsZQpERSA8LSB0b3BUYWJsZS5hbm5vdGF0ZWQuREUoREUuZGF0YSRlZml0LHAudmFsID0gMC4wNSkKaWYobnJvdyhERSkhPTApewogIHRhYmxlKERFWyxkaXJlY3Rpb25dKQogIERFW2RpcmVjdGlvbj09InVwLnJlZyIsLihkaXJlY3Rpb24sRU5TRU1CTCxTWU1CT0wsYWRqLlAuVmFsLGxvZ0ZDKV0KICBERVtkaXJlY3Rpb249PSJkb3duLnJlZyIsLihkaXJlY3Rpb24sRU5TRU1CTCxTWU1CT0wsYWRqLlAuVmFsLGxvZ0ZDKV0KCiNQaGVhdG1hcCB3LyBiYXRjaCBjb3JyZWN0aW9uCiAgaSA8LSBtYXRjaChERSRFTlNFTUJMLHJvd25hbWVzKERFLmRhdGEkdiRFKSkKICB5IDwtIHJlbW92ZUJhdGNoRWZmZWN0KERFLmRhdGEkdiRFW2ksXSxkZXNpZ24gPSBtb2RlbC5tYXRyaXgofmRydWcpLCBiYXRjaD0gcGR4KQogIGxhYmVscy5jb2wgPC0gcmVwKCIiLG5yb3coU1RHMTM5JG1ldGEpKQogIGxhYmVscy5yb3cgPC0gREUkU1lNQk9MCiAgYW5uLmNvbCA8LSBhcy5kYXRhLmZyYW1lKFNURzEzOSRtZXRhWywuKHBkeCxkcnVnKV0pCiAgcm93bmFtZXMoYW5uLmNvbCkgPC0gU1RHMTM5JG1ldGFbLFNhbXBsZS5uYW1lXQogIHBoZWF0bWFwKHksbGFiZWxzX2NvbD1sYWJlbHMuY29sLGxhYmVsc19yb3c9bGFiZWxzLnJvdyxhbm5vdGF0aW9uX2NvbCA9IGFubi5jb2wsc2NhbGU9InJvdyIpCn0KCiNHU0VBIC0gYzIKZ3NlYSA8LSBHU0VBLnJ1bihERS5kYXRhJHYsZCxjb250Lm1hdHJpeFssMV0sSHMuYzIsMC4wNSkKZ3NlYVtEaXJlY3Rpb249PSJVcCIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCmdzZWFbRGlyZWN0aW9uPT0iRG93biIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCgojR1NFQSAtIGM2CmdzZWEgPC0gR1NFQS5ydW4oREUuZGF0YSR2LGQsY29udC5tYXRyaXhbLDFdLEhzLmM2LDAuMDUpCmdzZWFbRGlyZWN0aW9uPT0iVXAiLC4ocm4sTkdlbmVzLERpcmVjdGlvbixGRFIpXQpnc2VhW0RpcmVjdGlvbj09IkRvd24iLC4ocm4sTkdlbmVzLERpcmVjdGlvbixGRFIpXQoKI3NzR1NFQSAtIGM2CnNzR1NFQS5kYXRhIDwtIHNzR1NFQS5ydW4oREUuZGF0YSR2JEUsSHMuYzYsZCxjb250Lm1hdHJpeD1jb250Lm1hdHJpeCkKCiNUb3AgREUgZ2VuZS5zZXRzIHRhYmxlCnNzR1NFQSA8LSB0b3BUYWJsZS5hbm5vdGF0ZWQuc3NHU0VBKHNzR1NFQS5kYXRhJGVmaXQpCmlmKG5yb3coc3NHU0VBKSE9MCl7CiAgc3NHU0VBW2RpcmVjdGlvbj09InVwLnJlZyIsLihkaXJlY3Rpb24sZ2VuZS5zZXQsYWRqLlAuVmFsLGxvZ0ZDKV0KICBzc0dTRUFbZGlyZWN0aW9uPT0iZG93bi5yZWciLC4oZGlyZWN0aW9uLGdlbmUuc2V0LGFkai5QLlZhbCxsb2dGQyldCn0KCmlmKG5yb3coc3NHU0VBKT4xKXsKICAjUGhlYXRtYXAgdy8gYmF0Y2ggY29ycmVjdGlvbgogIGkgPC0gbWF0Y2goc3NHU0VBJGdlbmUuc2V0LHJvd25hbWVzKHNzR1NFQS5kYXRhJHcpKQogIGxhYmVscy5jb2wgPC0gcmVwKCIiLG5yb3coU1RHMTM5JG1ldGEpKQogIGxhYmVscy5yb3cgPC0gc3NHU0VBJGdlbmUuc2V0CiAgYW5uLmNvbCA8LSBhcy5kYXRhLmZyYW1lKEhDSSRtZXRhWywuKHRyZWF0bWVudCldKQogIHJvd25hbWVzKGFubi5jb2wpIDwtIEhDSSRtZXRhWyxTYW1wbGUubmFtZV0KICBwaGVhdG1hcChzc0dTRUEuZGF0YSR3W2ksXSxsYWJlbHNfY29sPWxhYmVscy5jb2wsbGFiZWxzX3Jvdz1sYWJlbHMucm93LGFubm90YXRpb25fY29sID0gYW5uLmNvbCxzY2FsZT0icm93IikKfQpgYGAKCiMjIE9ubHkgSENJMDA5IChNb2RlbDogfiBkcnVnKQoKYGBge3J9CkhDSSA8LSBzdWJzZXQuUERYKHJuYXNlcSxybmFzZXEkbWV0YVssUERYPT0iSENJMDA5Il0pCnRyZWF0bWVudCA8LSBIQ0kkbWV0YVssVHJlYXRtZW50XQpzZXF1ZW5jaW5nIDwtIEhDSSRtZXRhWyxmYWN0b3IobWVyZ2VkLmxhbmVzKV0KZCA8LSBtb2RlbC5tYXRyaXgofiAwICsgdHJlYXRtZW50ICsgc2VxdWVuY2luZykKCmNvbnQubWF0cml4IDwtIG1hdHJpeChjKDEsLTEscmVwKDAsZGltKGQpWzJdLTIpKSwgZGltKGQpWzJdLCAxKQpjb2xuYW1lcyhjb250Lm1hdHJpeCkgPC0gYygiU2VsdS5taW51cy5jb250cm9sIikKcm93bmFtZXMoY29udC5tYXRyaXgpIDwtIGNvbG5hbWVzKGQpCmNvbnQubWF0cml4CgojUGVyZm9ybSBERQpERS5kYXRhIDwtIERFLnJ1bihIQ0kkaHVtYW4sZCwyLGNvbnQubWF0cml4ID0gY29udC5tYXRyaXgpCgojVG9wIERFIGdlbmVzIHRhYmxlCkRFIDwtIHRvcFRhYmxlLmFubm90YXRlZC5ERShERS5kYXRhJGVmaXQscC52YWwgPSAwLjA1KQppZihucm93KERFKSE9MCl7CiAgdGFibGUoREVbLGRpcmVjdGlvbl0pCiAgREVbZGlyZWN0aW9uPT0idXAucmVnIiwuKGRpcmVjdGlvbixFTlNFTUJMLFNZTUJPTCxhZGouUC5WYWwsbG9nRkMpXQogIERFW2RpcmVjdGlvbj09ImRvd24ucmVnIiwuKGRpcmVjdGlvbixFTlNFTUJMLFNZTUJPTCxhZGouUC5WYWwsbG9nRkMpXQoKI1BoZWF0bWFwIHcvIGJhdGNoIGNvcnJlY3Rpb24KICBpIDwtIG1hdGNoKERFJEVOU0VNQkwscm93bmFtZXMoREUuZGF0YSR2JEUpKQogIHkgPC0gcmVtb3ZlQmF0Y2hFZmZlY3QoREUuZGF0YSR2JEVbaSxdLGRlc2lnbiA9IG1vZGVsLm1hdHJpeCh+ZHJ1ZyksIGJhdGNoPSBwZHgpCiAgbGFiZWxzLmNvbCA8LSByZXAoIiIsbnJvdyhybmFzZXEkbWV0YSkpCiAgbGFiZWxzLnJvdyA8LSBERSRTWU1CT0wKICBhbm4uY29sIDwtIGFzLmRhdGEuZnJhbWUocm5hc2VxJG1ldGFbLC4ocGR4LGRydWcpXSkKICByb3duYW1lcyhhbm4uY29sKSA8LSBybmFzZXEkbWV0YVssU2FtcGxlLm5hbWVdCiAgcGhlYXRtYXAoeSxsYWJlbHNfY29sPWxhYmVscy5jb2wsbGFiZWxzX3Jvdz1sYWJlbHMucm93LGFubm90YXRpb25fY29sID0gYW5uLmNvbCxzY2FsZT0icm93IikKfQoKI0dTRUEgLSBjMgpnc2VhIDwtIEdTRUEucnVuKERFLmRhdGEkdixkLGNvbnQubWF0cml4WywxXSxIcy5jMiwwLjA1KQpnc2VhW0RpcmVjdGlvbj09IlVwIiwuKHJuLE5HZW5lcyxEaXJlY3Rpb24sRkRSKV0KZ3NlYVtEaXJlY3Rpb249PSJEb3duIiwuKHJuLE5HZW5lcyxEaXJlY3Rpb24sRkRSKV0KCiNHU0VBIC0gYzYKZ3NlYSA8LSBHU0VBLnJ1bihERS5kYXRhJHYsZCxjb250Lm1hdHJpeFssMV0sSHMuYzYsMC4wNSkKZ3NlYVtEaXJlY3Rpb249PSJVcCIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCmdzZWFbRGlyZWN0aW9uPT0iRG93biIsLihybixOR2VuZXMsRGlyZWN0aW9uLEZEUildCgojc3NHU0VBIC0gYzYKc3NHU0VBLmRhdGEgPC0gc3NHU0VBLnJ1bihERS5kYXRhJHYkRSxIcy5jNixkLGNvbnQubWF0cml4PWNvbnQubWF0cml4KQoKI1RvcCBERSBnZW5lLnNldHMgdGFibGUKc3NHU0VBIDwtIHRvcFRhYmxlLmFubm90YXRlZC5zc0dTRUEoc3NHU0VBLmRhdGEkZWZpdCkKaWYobnJvdyhzc0dTRUEpIT0wKXsKICBzc0dTRUFbZGlyZWN0aW9uPT0idXAucmVnIiwuKGRpcmVjdGlvbixnZW5lLnNldCxhZGouUC5WYWwsbG9nRkMpXQogIHNzR1NFQVtkaXJlY3Rpb249PSJkb3duLnJlZyIsLihkaXJlY3Rpb24sZ2VuZS5zZXQsYWRqLlAuVmFsLGxvZ0ZDKV0KfQoKaWYobnJvdyhzc0dTRUEpPjEpewogICNQaGVhdG1hcCB3LyBiYXRjaCBjb3JyZWN0aW9uCiAgaSA8LSBtYXRjaChzc0dTRUEkZ2VuZS5zZXQscm93bmFtZXMoc3NHU0VBLmRhdGEkdykpCiAgbGFiZWxzLmNvbCA8LSByZXAoIiIsbnJvdyhIQ0kkbWV0YSkpCiAgbGFiZWxzLnJvdyA8LSBzc0dTRUEkZ2VuZS5zZXQKICBhbm4uY29sIDwtIGFzLmRhdGEuZnJhbWUoSENJJG1ldGFbLC4odHJlYXRtZW50KV0pCiAgcm93bmFtZXMoYW5uLmNvbCkgPC0gSENJJG1ldGFbLFNhbXBsZS5uYW1lXQogIHBoZWF0bWFwKHNzR1NFQS5kYXRhJHdbaSxdLGxhYmVsc19jb2w9bGFiZWxzLmNvbCxsYWJlbHNfcm93PWxhYmVscy5yb3csYW5ub3RhdGlvbl9jb2wgPSBhbm4uY29sLHNjYWxlPSJyb3ciKQp9CmBgYAoKCg==